The submilli server commands talk to a running server over HTTP or
HTTPS. Out of the box they call http://127.0.0.1:8128 and send the token from
SUBMILLI_SERVER_TOKEN, so they need no setup in the shell that started
the server. From another machine, or from a deploy job, the address is
different and the token shouldn’t be typed.
This guide shows you how to point the submilli server commands at a
server.
Give it the token
Section titled “Give it the token”Without a token the server answers 401, and the commands say so:
error: the server did not accept this command's API token. Set `SUBMILLI_SERVER_TOKEN` to the token the server was started with, or `SUBMILLI_SERVER_TOKEN_FILE` to a file holding oneSet SUBMILLI_SERVER_TOKEN in the shell, or point --token-file, or
SUBMILLI_SERVER_TOKEN_FILE, at a file holding it. No flag takes the
token itself, so it never lands in the process list or in shell history.
On Kubernetes the chart keeps the tokens in a Secret. Read the admin one into a file first:
kubectl get secret submilli-auth -o jsonpath='{.data.admin-token}' | base64 -d > admin.tokenName the address
Section titled “Name the address”--server names the server, on every submilli server command, and
SUBMILLI_SERVER_URL sets it for a shell. Check the connection with
status, which needs the admin token:
export SUBMILLI_SERVER_URL=http://10.0.12.7:8128submilli server status --token-file admin.tokenstatus: runningbind: 0.0.0.0:8128pid: 39225active sessions: 0blueprints: supportUnder Compose the port is published on the host’s loopback, so the
commands work from the host without --server, and docker compose exec submilli submilli server status works from inside the container. On
Kubernetes, kubectl port-forward svc/submilli 8128:8128 brings the
server to your loopback for the length of a command.
Connect over HTTPS
Section titled “Connect over HTTPS”A server with HTTPS turned on is named with https:// and the host name
on its certificate:
submilli server status --server https://localhost:8128A certificate from a public authority needs nothing more, and the command prints the status as before.
Trust a self-signed certificate
Section titled “Trust a self-signed certificate”The CLI can’t check a self-signed certificate, or one from your organization’s authority, against the authorities it knows. So the first time, it shows the certificate’s public-key fingerprint and asks whether to trust it:
Server: localhost:8128Certificate names: localhostValid: Oct 3 17:03:03 2026 +00:00 to Oct 3 17:03:03 2027 +00:00Public-key fingerprint: sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29Verify this fingerprint with the server operator before approving.Trust this server public key? yesstatus: runningbind: 127.0.0.1:8128pid: 48439active sessions: 0blueprints: (none)Answer yes only after checking the fingerprint with whoever runs the server. Otherwise answer no, which is also the default. The operator reads the fingerprint from the certificate file:
openssl x509 -in server.crt -pubkey -noout \ | openssl pkey -pubin -outform DER \ | openssl dgst -sha256 \ | awk '{print "sha256:" $NF}'sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29A deploy job has no terminal to answer in, so there the command refuses and names the next step:
Error: server certificate is not approved; verify its public-key fingerprint independently, then run `submilli server trust add --server https://localhost:8128/ --fingerprint sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29`Register the fingerprint you checked before the job runs:
submilli server trust add --server https://localhost:8128 --fingerprint sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29Trusted localhost:8128 sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29The command refuses a fingerprint that isn’t the server’s. A mistyped one, or a server other than the one you checked, never gets trusted:
Error: server fingerprint mismatch: expected sha256:0000000000000000000000000000000000000000000000000000000000000000, received sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29Trust is kept per host and port, in ~/.submilli/server-trust.json (or
$SUBMILLI_HOME/server-trust.json):
submilli server trust listlocalhost:8128 sha256:5ee140a80e2613385387daa41b22fb98dddf3a6ad328d734fc369d6212dcce29A certificate renewed with the same key stays trusted. When the key
changes, check the new fingerprint, remove the old entry with
submilli server trust remove --server https://localhost:8128, and
trust the new one. An expired certificate, or one whose names don’t
include the host in --server, fails whatever you trusted.
Keep them in your shell
Section titled “Keep them in your shell”To stop passing the two on each command, put them in your shell’s
startup file (~/.zshrc or ~/.bashrc), with the token in a file that
only you can read:
export SUBMILLI_SERVER_URL=http://10.0.12.7:8128export SUBMILLI_SERVER_TOKEN_FILE=$HOME/.submilli/servers/prod/tokenFrom then on each new shell is connected, and submilli server status
needs no flags.
Switch between servers
Section titled “Switch between servers”With more than one server, say staging and production, keep each one’s address and token in a separate directory:
~/.submilli/servers/staging/url http://10.0.12.7:8128~/.submilli/servers/staging/token~/.submilli/servers/prod/url http://10.0.20.4:8128~/.submilli/servers/prod/tokenThen a small function in ~/.zshrc or ~/.bashrc switches the two
variables by name, and refuses a name with no directory:
submilli-use() { local dir=~/.submilli/servers/$1 [ -d "$dir" ] || { echo "no server named '$1' under ~/.submilli/servers" >&2; return 1; } export SUBMILLI_SERVER_URL=$(cat "$dir/url") export SUBMILLI_SERVER_TOKEN_FILE=$dir/token}submilli-use stagingsubmilli server statusstatus: runningbind: 0.0.0.0:8128pid: 39225active sessions: 0blueprints: supportThe switch lasts for the shell it runs in. To start each shell on one
server, make submilli-use staging the last line of ~/.zshrc or
~/.bashrc.
Which commands need the admin token
Section titled “Which commands need the admin token”A user token, the kind an application holds, runs programs and reads.
Anything that changes the server needs admin:
| Token | Commands |
|---|---|
user or admin |
run-code, session open and close, docs |
admin only |
status, blueprint …, packages …, secret …, mcp …, stop |
The server refuses a user token on an admin command because of its
role, not its value:
error: this endpoint needs a token with the `admin` role; the token sent has the `user` roleRun the server shows how to declare a
user token. The CLI reference lists each
submilli server command and its options.