Remote Control
With remote control the EVAnalyzer user interface runs on your own computer, while everything heavy happens on another machine - typically a GPU workstation or an analysis server that already holds the images. Images, projects and results stay on that machine; only image tiles for the viewer, preview results and pages of the results table travel over the network.
Both front ends support it: the GUI and the command line interface. They behave exactly as they do locally - only the place where the work happens changes.
How it works
Section titled “How it works”Three roles take part, all provided by the same evanalyzer binary:
| Role | Command | Runs on | Job |
|---|---|---|---|
| Client | evanalyzer --remote … | Your computer | The normal GUI or CLI. Instead of reading files and running pipelines itself, it sends every request to the server. |
| Server | evanalyzer server | Server machine | The entry point clients connect to. It checks the login, starts a worker for the user and from then on tunnels the connection to it. |
| Worker | evanalyzer worker | Server machine | One compute instance per user. It opens images, runs previews, analyses and trainings, queries and exports results - all on the server. |
A connection goes through these steps:
- The client connects to the server (default port
7400) over an encryptedwss://connection and logs in with user name and password. - The server starts a worker for this user - or, if one is already running, reattaches to it. The worker only listens on
127.0.0.1on a free port, so it can’t be reached from outside directly; the server passes the connection on to it. - From now on client and worker talk directly through this tunnel. The worker reads the images, runs the pipelines and writes the results database on the server’s disks.
Each user gets their own worker process, which can only read and write the user’s allowed folders. Every login of the same user - a second window, the CLI, a reconnect - lands on the same worker.
Quick start
Section titled “Quick start”1. Start the server
Section titled “1. Start the server”On the server machine:
./evanalyzer server --listen 0.0.0.0:7400Without --listen the server only accepts connections from the machine itself (127.0.0.1:7400). When listening on every network (0.0.0.0), the log lists the addresses clients can use - the host name and every IP address of the machine.
On first start the server creates a self-signed TLS certificate and logs its fingerprint - at every start:
Clients connect with wss:// - certificate fingerprint 1E:0F:D0:…:23:5DGive that fingerprint to your users - see Encryption.
Out of the box the server knows a single account, admin. Unless you configure a password for it, the server makes up a random one at every start and prints it to the console (only there, not in the log):
Log in as 'admin' with password: …That password is valid until the server stops. To keep a fixed password, or to set up several accounts, use a configuration file. The admin’s worker is confined to a folder of its own (see Users), so it can’t reach anything else on the machine until you add allowed folders.
2. Connect the GUI
Section titled “2. Connect the GUI”Open EVA › Connect to server… (or Connect to a server… on the Start page), enter the Server (e.g. wss://workstation:7400), User and Password, and click Connect. Servers used before are listed under Recent servers - click one to fill in the address and user.
On the first connection to a server, EVAnalyzer shows the fingerprint of its certificate (Is this your server?). Compare it with the fingerprint your administrator gave you and click They match - connect only if they do. The certificate is then remembered on this computer. If the server later presents a different certificate, EVAnalyzer warns (The server’s certificate has changed) and shows the old and new fingerprints: either the administrator replaced the certificate - or someone is intercepting the connection, in which case don’t connect.
The window then switches to the server. EVA › Connect to other server… switches to another one, EVA › Disconnect returns to this computer. The bottom bar always shows where you work.
You can also connect when starting EVAnalyzer:
./evanalyzer --remote wss://workstation:7400 --user alice --remote-fingerprint 1E:0F:D0:…:23:5DEVAnalyzer asks for the password in the terminal, then opens the normal window.
Everything you open or save now refers to the server:
- The status bar shows where you are working: This computer when local, or a alice @ workstation:7400 badge when connected. A lock icon shows that the connection is encrypted and the server verified; otherwise the badge says - unencrypted or - server not verified.
- The file browser, which EVAnalyzer uses for every open and save, lists the server’s folders (shown as Server locations). Paths you pick are paths on the server.
- Running an analysis, the live preview, AI training and result exports all run on the server.
3. Use the CLI remotely
Section titled “3. Use the CLI remotely”Add the same options to any CLI command:
./evanalyzer cli --remote wss://workstation:7400 --user alice --remote-fingerprint 1E:0F:… \ analyze --project /data/experiment-12/experiment.evaprojAll paths - --project, --images, --db, --out - are paths on the server, and output files (such as an exported CSV) are written there as well.
Analyses run in the background
Section titled “Analyses run in the background”An analysis belongs to the worker, not to the connection that started it. Closing the window, a dropped network or a laptop going to sleep don’t stop it:
-
GUI - closing the window or choosing Disconnect while an analysis runs asks what to do: Keep running on server (or Keep running and disconnect) leaves it running, Cancel analysis stops it. The next time you connect, the GUI follows the running analysis again and reports analyses that ended in the meantime.
-
CLI - if the connection drops during
analyze, the analysis keeps running on the server.evanalyzer cli jobslists the running and recently finished analyses,evanalyzer cli attachfollows the running one again (--job <id>for a specific one):Terminal window ./evanalyzer cli --remote wss://workstation:7400 --user alice jobs./evanalyzer cli --remote wss://workstation:7400 --user alice attach
Each user runs one analysis at a time - a second one is refused until the first has finished. A classifier training survives a disconnect too: the worker saves the model into the project’s models folder itself. Previews and exports stop with their connection.
A results database records how its analysis ended. One that was cancelled, failed or interrupted (crash, killed worker) shows a warning in the results window and in evanalyzer cli view.
Reconnecting
Section titled “Reconnecting”When the connection drops, a banner at the top of the window says so and the status badge turns into … - disconnected. The GUI reconnects by itself - after 2, 5 and 10 seconds, then every 30 seconds, or at once with Reconnect now in the banner. It reuses the session it logged in with, so no password is needed as long as the user’s worker is still running. Open images and results carry on.
Server configuration
Section titled “Server configuration”The server is configured with a TOML file:
./evanalyzer server --config /etc/evanalyzer/server.tomlEach setting is taken from the first of these that sets it: the command-line arguments (--listen, --session-store, --log-level), the --config file, the built-in defaults. The server reads no environment variables and no config file unless you pass --config. It reads the files once at startup, so restart it after editing them. Unknown or misspelled keys and impossible values stop the server at startup with an error that names the key.
A complete example with every setting and its default:
# Address and port to accept clients on. 127.0.0.1 = this machine only;# 0.0.0.0:7400 accepts connections from every network.listen = "127.0.0.1:7400"
# File the running workers are recorded in, so a restarted server finds them# again. Default: /run/evanalyzer/sessions.json for a system service,# otherwise in the temp folder.# session_store = "/run/evanalyzer/sessions.json"
# error, warn, info, debug, trace, off - or per module,# e.g. "info,evanalyzer_core=debug".log_level = "info"
[users]# Who may log in: "single", "linux" or "file" - see Users below.source = "single"# Folders every user's worker may read and write, unless the account sets# its own allowed_dirs. {home} stands for the user's home folder.default_allowed_dirs = ["{home}"]
[users.single]username = "admin"# Hashed password, create one with `evanalyzer hash-password`.# Default: none - a random password is made up at every start and# printed to the console.# password = "$argon2id$v=19$m=19456,t=2,p=1$…"# Default: a folder of its own, created on start (see Users below).# home = "/srv/evanalyzer/admin"# allowed_dirs = ["{home}", "/data/microscopy"]
[users.linux]shadow_file = "/etc/shadow"passwd_file = "/etc/passwd"# [users.linux.overrides.alice]# allowed_dirs = ["{home}", "/data/shared"]
[users.file]# path = "/etc/evanalyzer/users.toml"
[tls]enabled = true# cert = "/etc/evanalyzer/cert.pem"# key = "/etc/evanalyzer/key.pem"# self_signed_dir = "/var/lib/evanalyzer/tls"
[workers]# A worker stops by itself once no client has been connected and no# analysis has run for this many minutes. At least 1.idle_timeout_minutes = 120
[limits]# Not set: no limit.# max_workers = 20# max_connections = 100[users] source chooses where accounts come from:
source | Accounts | Home folder | Worker runs as |
|---|---|---|---|
single (default) | One account in [users.single]: admin, with a random password made up at every start and printed to the console unless users.single.password is set | users.single.home, default: a folder of its own - /var/lib/evanalyzer/single-user as a system service, otherwise evanalyzer/single-user in the server account’s data folder (~/.local/share on Linux, %LOCALAPPDATA% on Windows, ~/Library/Application Support on macOS) | the server’s account |
linux | This machine’s system users, checked against /etc/shadow. The server needs root or membership in the shadow group. | from /etc/passwd | the user’s own account, if the server runs as root |
file | The [[user]] entries of a separate users file, [users.file] path. No system accounts needed. | home of each entry | the server’s account |
A users file for source = "file" lists one [[user]] table per account:
[[user]]id = "1" # stable - change the name, never the idname = "alice" # login name, can be changed freelypassword = "$argon2id$v=19$m=19456,t=2,p=1$…"home = "/srv/evanalyzer/alice" # absolute; the worker's working directoryallowed_dirs = ["{home}", "/data/microscopy/shared"] # optional
[[user]]id = "2"name = "bob"password = "$2b$12$…"home = "/srv/evanalyzer/bob"Allowed folders
Section titled “Allowed folders”A worker can read and write only its user’s allowed folders and the user’s EVAnalyzer folder, which holds settings and templates. The allowed folders come from:
- the account’s own
allowed_dirs:users.single.allowed_dirs, anallowed_dirsentry in the users file, or[users.linux.overrides.<name>]; - otherwise
users.default_allowed_dirs, which defaults to["{home}"].
{home} stands for the user’s home folder. For example, this gives everyone their home plus a shared data folder:
[users]default_allowed_dirs = ["{home}", "/data/microscopy"]Passwords
Section titled “Passwords”Create a password entry with EVAnalyzer itself:
./evanalyzer hash-password # asks twice, hidden; prints the hashecho 'PASSWORD' | ./evanalyzer hash-password # for scriptsIt prints an Argon2id hash with a random salt. Use it as the value of password = "...". Hashes made with other tools are accepted too:
| Format | Looks like | Generate with |
|---|---|---|
| Argon2id (recommended) | $argon2id$v=19$m=… | evanalyzer hash-password |
| bcrypt | $2b$12$… (also $2a$, $2y$) | htpasswd -nbBC 12 "" 'PASSWORD' | cut -d: -f2 (apache2-utils) |
| yescrypt | $y$… | mkpasswd -m yescrypt (whois) |
| sha512-crypt / sha256-crypt | $6$… / $5$… | openssl passwd -6 |
| plain text | plain:PASSWORD | testing only - the server warns at startup |
Anyone who can read the hashes can try to crack them offline, so make the files readable only by the server’s account (chmod 600). The server warns at startup if other accounts can read the users file.
Encryption (TLS)
Section titled “Encryption (TLS)”Connections between clients and the server are encrypted by default (wss://). Workers listen on 127.0.0.1 only and are reached unencrypted.
- Self-signed certificate (default). The server creates it on first start in
tls.self_signed_dirand logs its fingerprint at every start. Users confirm the fingerprint once in the GUI, or pass it with--remote-fingerprinton the command line - without it, the command-line client refuses to connect and prints the fingerprint it was shown. Keepself_signed_dir(include it in backups) and the fingerprint stays the same. - Certificate from a public authority (e.g. Let’s Encrypt): set
tls.certandtls.key. Clients connecting by that host name need no fingerprint. A certificate from your organisation’s own CA works too, with the fingerprint, like a self-signed one. - Without encryption:
tls.enabled = false, and clients usews://. Only for a server behind something that encrypts already (reverse proxy, VPN, SSH tunnel) or for tests on one machine - the server warns when it listens on the network without TLS, and the client’s status bar shows unencrypted.
For tests or a network you fully trust, clients can skip the certificate check with --no-tls-verification: still encrypted, but anyone in between could pose as the server and read the password. The status bar then shows server not verified.
Workers
Section titled “Workers”A worker keeps running when its client disconnects or logs out, and when the server restarts (the server finds it again through session_store). It stops by itself once no client has been connected and no analysis has run for workers.idle_timeout_minutes (default 2 hours); the user’s next login starts a new one.
The server starts each worker with the user’s home as working directory and an environment cleared of everything except what the OS needs.
Limits
Section titled “Limits”[limits] protects the machine from more work than it can do:
max_workers- users working at the same time. A login that would start one more worker is refused with “try again later”; users whose worker is already running can always log in.max_connections- open client connections, all users together (one GUI or CLI is one connection).
Running the server as a service (Linux)
Section titled “Running the server as a service (Linux)”-
Install the release archive, e.g. to
/opt/evanalyzer(the bundled libraries must stay next to the binary):Terminal window sudo mkdir -p /opt/evanalyzersudo tar xzf evanalyzer-linux-x86_64.tar.gz -C /opt/evanalyzer -
Configure
/etc/evanalyzer/server.toml. Set at leastlisten = "0.0.0.0:7400"and the users. For the paths used by the unit below, also setsession_store = "/run/evanalyzer/sessions.json"[tls]self_signed_dir = "/var/lib/evanalyzer/tls" -
Create
/etc/systemd/system/evanalyzer.service:[Unit]Description=EVAnalyzer serverWants=network-online.targetAfter=network-online.target[Service]ExecStart=/opt/evanalyzer/evanalyzer server --config /etc/evanalyzer/server.toml# Runs as its own account - right for users.source = "single" or "file".# For users.source = "linux" remove these two lines: that needs root.User=evanalyzerGroup=evanalyzerRuntimeDirectory=evanalyzerRuntimeDirectoryMode=0700StateDirectory=evanalyzerStateDirectoryMode=0700# Workers - and the analyses running in them - survive a restart of the# server: stop only the server process and keep the session file.KillMode=processRuntimeDirectoryPreserve=yesRestart=on-failureRestartSec=5[Install]WantedBy=multi-user.target -
Start it:
Terminal window sudo useradd --system --no-create-home --shell /usr/sbin/nologin evanalyzer # not for "linux" userssudo chown -R root:evanalyzer /etc/evanalyzer && sudo chmod 640 /etc/evanalyzer/*.tomlsudo systemctl daemon-reloadsudo systemctl enable --now evanalyzerjournalctl -u evanalyzer -f # the log - including the TLS fingerprintOpen port 7400/tcp in the firewall (e.g.
sudo ufw allow 7400/tcp).
With User=evanalyzer, workers run as that account: it needs read/write access to the users’ home folders and allowed folders. systemctl restart evanalyzer keeps running workers and analyses. To stop everything at once, e.g. before updating the binary, use sudo systemctl kill --signal=SIGTERM evanalyzer - this stops the workers too, and with them any running analysis.
Connecting without a server
Section titled “Connecting without a server”For a quick one-user setup you can skip the server and start a worker by hand. The worker then authenticates clients with a token instead of a user login:
# On the server machine./evanalyzer worker --listen 0.0.0.0:7400 --root /data --root /scratchIf no --token is given, the worker generates one and prints it at startup. Connect with that token instead of --user:
# On your computer./evanalyzer --remote ws://server-name:7400 --remote-token <token>The worker speaks plain ws:// - only use it on a trusted network or through an SSH tunnel. --root limits which folders the client may browse and use; without it, the client can reach every file the worker process can (a warning is printed at startup).
Command-line options
Section titled “Command-line options”Client options
Section titled “Client options”These options work for the GUI and every cli command:
| Option | Description |
|---|---|
--remote <URL> | Server or worker to work on instead of this computer, e.g. wss://workstation:7400 (ws:// if the server runs without TLS). |
--user <USER> | User to log in as on an evanalyzer server. Requires --remote. |
--password <PASSWORD> | Password for --user. If omitted, it is asked for (hidden) in the terminal. Note that command-line arguments are visible to other users of the same computer. |
--remote-fingerprint <SHA256> | SHA-256 fingerprint of the server’s TLS certificate, as the server logs it at startup. Needed for the server’s own self-signed certificate. |
--no-tls-verification | Accept any certificate without checking it. Only for tests and trusted networks; can’t be combined with --remote-fingerprint. |
--remote-token <TOKEN> | Connect directly to an evanalyzer worker with the token it printed, instead of --user. |
--log-level <FILTER> | What to log: error, warn, info (default), debug, trace, off, or per module, e.g. info,evanalyzer_core=debug. |
--remote needs either --user (server) or --remote-token (worker); the two can’t be combined.
evanalyzer server
Section titled “evanalyzer server”| Option | Default | Description |
|---|---|---|
--config <FILE> | - | Configuration file (TOML). |
--listen <ADDR> | 127.0.0.1:7400 | Address and port to accept clients on. |
--session-store <FILE> | see above | File the running workers are recorded in. |
evanalyzer worker
Section titled “evanalyzer worker”| Option | Default | Description |
|---|---|---|
--listen <ADDR> | 127.0.0.1:7400 | Address to listen on. |
--token <TOKEN> | generated | Token clients must present. Generated and printed if not set. |
--root <FOLDER> | - | Folder clients may browse and use. Repeat for several folders. Without it, nothing is restricted. |
--home <FOLDER> | this account’s | Home folder of the user this worker serves; its user folder (templates) lives below it. |
--idle-timeout <MINUTES> | - | Stop once no client has been connected and no analysis has run for this long. |
Workers started by evanalyzer server get all of these from the server - you only start a worker by hand for the direct connection.
evanalyzer hash-password
Section titled “evanalyzer hash-password”Prints an Argon2id hash of a password for the server’s config or users file. Asks for the password twice (hidden), or reads one line from stdin when it is not a terminal.
Security
Section titled “Security”- A logged-in user’s worker can read and write only the user’s allowed folders. Keep them as narrow as your users need.
- Set a password for the admin account (or switch to
linuxorfileusers) when the server should run permanently - the random password changes at every restart. - Distribute the certificate fingerprint over a channel you trust, and don’t use
--no-tls-verificationoutside of tests. - Make the config and users files readable only by the server’s account.
- Treat worker tokens like passwords, and use
--rooton a hand-started worker. - Prefer the password prompt over
--password- command-line arguments show up in the process list.
Requirements and limitations
Section titled “Requirements and limitations”- Compatible versions. Client and server must speak the same remote protocol version. Their EVAnalyzer versions may differ. If the protocol versions don’t match, the connection is refused with a message naming both versions.
- Paths refer to the server. Projects reference images by their path on the server, so a project created remotely opens locally only if the same paths exist there.
- One analysis per user. A second analysis is refused while the first is still running.
- Previews and exports don’t survive a dropped connection - analyses and trainings do.