Run Visor on a Linux host
Run Visor directly on the host as a regular process. Postgres can still come from Docker or any managed provider — only Visor itself runs as a native binary here.
Prerequisites
- Go 1.25+ (only for building from source).
- A reachable PostgreSQL instance whose DSN matches
db.url— see Set up database. - A reachable Bridgeless-core node (RPC + gRPC) — see Nodes.
- The TSS binary itself plus its YAML config, TLS certificates and Vault secrets, prepared by following the previous guide:
Recommended on-disk layout
Pick a deployment root and lay the files out as follows. The absolute paths
below are what you put into config.yaml.
/opt/tss-wrapper/
├── tss-wrapper-svc # Visor binary (built in the next step)
├── config.yaml # Visor config
└── binary/
├── tss # TSS binary -> tss.binary_path
└── configs/
├── tss.yaml # TSS binary config -> tss.config_path
└── certs/ # certificates dir -> tss.certificates_path
Requirements:
tss.binary_pathmust be an absolute path to an executable file. Visor launches it withtss.binary_paramsfor default mode and, during tasks, re-launches it with--config <tss.config_path>.tss.config_pathis the TSS binary's own YAML. Visor mutatesparties.listhere during a reshare, and thetimechangertask rewrites timing fields in it. Start from the config you produced in Configuration file.tss.certificates_pathmust be a directory writable by Visor and readable by the TSS binary. Party certificates are written as<domain>.crt. The initial certificates come from TLS certificates.
Matching config.yaml snippet:
tss:
binary_path: "path/to/binary/tss"
binary_params: ""
api_params: ""
config_path: "path/to/binary/tss/tss.yaml"
certificates_path: "path/to/binary/tss/certs"
core_address: "bridge1..."
See Configuration file for the full field reference.
1. Build Visor
From a clone of the tss-wrapper-svc repo:
go build -o tss-wrapper-svc .
install -m 0755 tss-wrapper-svc /opt/tss-wrapper/tss-wrapper-svc
2. Start Postgres (if you don't already have one)
Any Postgres instance works; the upstream repo bundles one for convenience:
docker compose -f build/docker-compose.yaml up -d db
This exposes Postgres on localhost:5435 with:
- user:
tss-wrapper - password:
tss-wrapper - db:
db
Make sure db.url in your config.yaml matches, for example:
db:
url: postgres://tss-wrapper:tss-wrapper@localhost:5435/db?sslmode=disable
For alternative Postgres setups, see Set up database.
3. Passing the config file
Every tss-wrapper-svc subcommand accepts -c / --config and defaults to
./config.yaml:
tss-wrapper-svc service run --config /opt/tss-wrapper/config.yaml
tss-wrapper-svc service run -c /opt/tss-wrapper/config.yaml
tss-wrapper-svc service migrate up -c /opt/tss-wrapper/config.yaml
tss-wrapper-svc service migrate down -c /opt/tss-wrapper/config.yaml
4. Apply DB migrations
Run once against each fresh database:
cd /opt/tss-wrapper
./tss-wrapper-svc service migrate up -c ./config.yaml
This creates Visor's epochs, latest_block and tasks tables.
5. Run Visor
cd /opt/tss-wrapper
./tss-wrapper-svc service run -c ./config.yaml
You should see the orchestrator log started default mode once Visor has
launched the TSS binary.
6. Verify
- HTTP gateway:
curl http://localhost:8080/
- gRPC:
grpcurl -plaintext localhost:9090 list
- Logs should include the orchestrator line
started default modeand observer lines for events consumed from Bridgeless-core.
7. Run Visor as a systemd unit
[Unit]
Description=TSS Visor service
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/tss-wrapper
ExecStart=/opt/tss-wrapper/tss-wrapper-svc service run -c /opt/tss-wrapper/config.yaml
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.target
Enable and inspect:
systemctl daemon-reload
systemctl enable --now tss-wrapper
journalctl -u tss-wrapper -f
Visor will drive the TSS binary end-to-end from this point on. Epoch
transitions trigger auto_resharing automatically — the manual flow
documented in Key resharing is only needed for
one-off operations or disaster recovery.