Skip to content
Talk to our solutions team

Deploy: Single-Node

Audience: DevSecOps — engineers deploying vault.svc (the Vault service) as a single instance backed by HCP Vault (or OpenBao). You are either a customer employee operating a Vault for your company, or a kis.ai employee operating one on the customer’s behalf. Either way, this guide assumes you do not have the Vault source code — you have a release tarball, a binary, and a config file to write. Everything here can be done with what’s in the tarball.

Appropriate for: smaller production deployments, customer-prem single-site installations, and dev / staging environments where the trust-plane availability requirement is lower than the consuming platform.

For HA deployments with multiple vault.svc instances, see the HA deployment guide. For deploying vault-agent on each consumer node, see the agent guide.

RequirementDetail
OSLinux x86_64 / arm64. macOS supported for dev only.
Privileged userService runs as vault. Do not run as root.
Backend storageA running HCP Vault, OpenBao, Azure Key Vault, or AWS Secrets Manager (HCP/OpenBao are the only ones supported end-to-end in v1; Azure/AWS are scaffolded but phase-4).
FilesystemA persistent local directory for state and cert material (default /var/lib/vault, /etc/vault).
NetworkOne TCP port (default :7999). Outbound to the backend (HCP: 8200; etc.). Outbound HTTPS to Chitragupta (audit.svc, typically :8443) for audit submission.
TLS materialmTLS required. PEM-format server cert/key, the CA bundle that signs your clients, and (for HCP/OpenBao) a separate client cert for vault.svc → backend Vault auth.
TimeNTP-synced. JWT nbf/exp and cert validity windows assume reasonable wall-clock accuracy.
Terminal window
sudo install -d -o root -g root /opt/vault
sudo tar -C /opt/vault -xzf vault.svc-${VERSION}-linux-amd64.tar.gz
sudo install -d -o root -g vault -m 0750 /etc/vault
sudo install -d -o vault -g vault -m 0700 /var/lib/vault
sudo install -d -o root -g vault -m 0750 /etc/vault/certs
/etc/systemd/system/vault.svc.service
[Unit]
Description=vault.svc trust plane (kis Vault server)
After=network.target
[Service]
Type=simple
User=vault
Group=vault
ExecStart=/opt/vault/vault.svc server -f /etc/vault/vault.yaml
Restart=on-failure
RestartSec=2
LimitNOFILE=65536
# Hardening — single-node, no shared FS:
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/vault /var/log/vault
NoNewPrivileges=true
PrivateTmp=true
LockPersonality=true
RestrictSUIDSGID=true
# Resource limits.
MemoryMax=1G
TasksMax=256
[Install]
WantedBy=multi-user.target
Terminal window
sudo systemctl daemon-reload
sudo systemctl enable --now vault.svc

Generate a template:

Terminal window
sudo /opt/vault/vault.svc config generate bootstrap > /etc/vault/vault.yaml
# Or pick a specific shape:
sudo /opt/vault/vault.svc config list

Edit /etc/vault/vault.yaml. Production-style example using HCP Vault (works against OpenBao identically — swap hcpvaultopenbao and the cert paths):

# Service identity — chassis convention.
service: vault
version: 1.0.0
sid: ${HOSTNAME}
# Listener.
host: ""
port: "7999"
zerotrust: true
# Storage backend — HCP Vault (KV-v2) with cert auth.
vaultmanager:
store:
hcpvault:
url: https://vault.internal.example.com:8200
certpath: /etc/vault/certs/vault-client.crt
keypath: /etc/vault/certs/vault-client.key
cacertpath: /etc/vault/certs/issuer.crt
authname: vault-cert
secretspathprefix: secret
certificatespathprefix: kisaicerts
retryduration: 2s
# Signing custody — start with inproc; upgrade to pkcs11 / awskms once
# the HSM/KMS plan is in place. See signer-*.yaml examples. The signer
# lives under the service's internal namespace (`horus`).
horus:
signer:
type: inproc
# JWT defaults.
servicejwt:
expiry: 1h
httponly: true
# Default transport for the chassis lib-vault clients in this cluster.
# Keep "remote" until every consumer node has vault-agent installed
# and validated — flipping to "agent" before that breaks consumers.
vault:
client:
transport: remote
# Tenant-aware access rules. See accessrules.yaml example for the
# canonical shape, including the mandatory tenant check.
accessrules: {}
# Audit emission. Required in prod; the default NoOpEmitter is dev-only.
audit:
endpoint: https://chitragupta.internal:8443/submit
timeout: 5s
# OTLP telemetry.
telemetry:
collector: otel-collector.internal:4317
insecure: false
environment: prod
traces: { enabled: true, sampling_rate: 0.1 }
Terminal window
vault.svc config list # list all
vault.svc config generate bootstrap # HCP + inproc + JS rules
vault.svc config generate bootstrap-dev # FsVault (dev only)
vault.svc config generate backend-openbao # OpenBao snippet
vault.svc config generate backend-azurekv # Azure KV snippet (phase-4)
vault.svc config generate backend-awssm # AWS SM snippet (phase-4)
vault.svc config generate signer-pkcs11 # HSM signer (phase-5)
vault.svc config generate signer-awskms # AWS KMS signer (phase-5)
vault.svc config generate accessrules # canonical JS rule sample
vault.svc config generate agent # reference per-node agent config

A one-time bootstrap of the backend, per the release documentation. Summary:

  1. vault operator init (or bao operator init), unseal with the issued keys, store the root token offline.
  2. vault auth enable cert — turn on certificate auth.
  3. Write the kisai-policy granting access to secret/* and kisaicerts/*.
  4. vault write auth/cert/certs/vault-cert display_name=vault_cert policies=kisai-policy certificate=@/etc/vault/certs/vault-client.crt
  5. vault secrets enable -path=secret kv-v2
  6. vault secrets enable -path=kisaicerts kv-v2

Then point vault.svc’s bootstrap (vaultmanager.store.hcpvault.*) at the URL + cert paths + the registered authname (vault-cert above). Validate with vault.svc startup logs — the first successfully connected to vault backend hcpvault should land within 2 s of boot.

For any non-loopback deployment, two cert pairs:

PairPurposeWhere
Server certTerminates incoming mTLS from consumers / operatorhost/port listener
Vault client certAuthenticates vault.svc to HCP/OpenBaovaultmanager.store.hcpvault.{certpath,keypath}

Same CA bundle for both (the cluster’s kisai issuer chain). Generate with vault.svc cert rootca / intermediateca / svccert (the release documentation covers the procedure end-to-end), or with your existing CA.

Terminal window
# Lock down perms
sudo chown -R root:vault /etc/vault/certs
sudo chmod -R 0640 /etc/vault/certs/*.key
sudo chmod 0644 /etc/vault/certs/*.crt
Terminal window
sudo systemctl start vault.svc
sudo systemctl status vault.svc

Verify:

Terminal window
curl -s http://localhost:7999/version # unauth
curl -s http://localhost:7999/ready # 200 → ready
curl -s --cert client.crt --key client.key --cacert ca.crt \
https://localhost:7999/certificate/internal/issuer

Tail logs:

Terminal window
journalctl -u vault.svc -f

Look for successfully connected to vault backend hcpvault (or your backend’s name) within 2 s of start.

From any host with the kis CLI:

Terminal window
kis vault status --server https://vault.example.com:7999
kis vault audit query --since 1h
kis vault node-token issue --scope dc=us-west,cluster=prod

Operator auth: an mTLS operator cert resolved from the kis context or --operator-cert / --operator-key. The server enforces the operator-role scope.

7.2 Issuing a join token (for a vault-agent)

Section titled “7.2 Issuing a join token (for a vault-agent)”
Terminal window
kis vault node-token issue \
--scope dc=us-west,cluster=prod \
--ttl 1h \
--uses 1
# → hj_v1_n8x2k_a1b2c3d4e5f6g7h8j9k0

Give the printed token to the operator running vault-agent init on the new node. See the agent guide.

Terminal window
kis vault audit query --since 24h --actor 'spiffe://kis.ai/customer/acme/...'
kis vault audit verify # walks the chain from genesis

audit verify is slow (whole-chain replay); run it as a periodic CI job rather than interactively.

Terminal window
kis vault put vault:db_password "$(openssl rand -hex 24)" \
--end-date "$(date -u -d '+90 days' +%Y-%m-%dT%H:%M:%SZ)"

The previous active record is marked inactive in the entity store but the corresponding vault blob is not deleted immediately; the janitor sweeps expired blobs after a grace window.

Two stores:

  1. Backend (HCP Vault / OpenBao / Azure KV / AWS SM) — the source of truth for secret + cert material. Backup is the backend’s responsibility (Vault Raft snapshots, AWS SM is implicitly backed up, Azure KV has its own export). Confirm your backend’s backup procedure runs.

  2. Data API audit + entity tablesvault.svc writes to these. Audit is ALSO mirrored to Chitragupta (audit.svc) for chain durability; the Data API copy is the queryable index. Backup is the Data API operator’s responsibility.

The vault.svc binary itself is stateless — losing the host doesn’t lose data so long as the backend + Data API survive.

  1. Provision a new host, same OS, same package install (§2).
  2. Copy /etc/vault/vault.yaml and /etc/vault/certs/* from config-as-code (your cluster repository).
  3. sudo systemctl start vault.svc.
  4. Verify /ready returns 200 and the connect log fires within 2 s.

No backend or audit state needs reconstruction; vault.svc picks up where the previous instance left off.

Terminal window
sudo systemctl stop vault.svc
sudo tar -C /opt/vault -xzf vault.svc-${NEW_VERSION}-linux-amd64.tar.gz
sudo systemctl start vault.svc

Downtime: typically <2 s; consumers using RemoteVaultClient auto-retry. Read the release notes before crossing a minor version boundary — backend or signer interface changes are surfaced there.

SymptomLikely causeAction
/ready returns 503Backend not reachable / not authenticated.journalctl -u vault.svc -n 200 — look for failed to connect to <backend>. Verify the backend is up, the auth role exists, the cert file is readable by the vault user.
vault.svc: refusing prod (fsvault)Mistake — fsvault is configured with env: prod.Switch the backend to hcpvault / openbao / your real prod backend.
TLS handshake fails on listenerServer cert + client cert chain mismatch.Verify the CA bundle (cacertpath) signs both. Check cert expiry: openssl x509 -in cert.crt -noout -enddate.
Vault token “non-renewable” error in logsThe cert role lacks auth/token/renew-self permission.Re-apply kisai-policy on the backend.
Audit emission failingChitragupta endpoint unreachable.Verify audit.endpoint resolves and is reachable. Until fixed, no operations are blocked — but the chain is not durable. Investigate immediately.
vault.svc config list returns no examplesBroken release binary — examples weren’t embedded at build time.Re-download the release tarball and verify checksum; if it persists, file a bug with the build supplier.
Consumer-side vault.client.transport: agent returns “not yet implemented”Expected in v1. The agent transport is scaffolded; flip back to remote until phase-2 lands.See the consumer guide.

Process crash: systemd restart kicks in. Backend state is unaffected (it’s external). Consumers using RemoteVaultClient retry transparently via lib-chassis backoff. Total recovery: under 5 s in normal operation.

Backend down: vault.svc’s connect loop retries (retryduration). While the backend is unreachable, in-flight secret operations fail with vault-failed-to-retrieve-secret / vault-not-connected. Consumers do NOT have a local cache today (the lib-vault secret cache is wired but disabled — see the consumer guide). Audit + cert verification paths that rely on cached cert public keys keep working.

Single-node has no redundancy. If the host dies, restore per §8.2. For deployments that need fault tolerance, see the HA deployment guide.

  • All TLS material has not_after: ≤ 12 months. Rotation schedule documented.
  • vault.client.transport set explicitly (don’t rely on the default during a migration).
  • FsVault NEVER referenced in this cluster’s config (search: grep -r fsvault /etc/vault/).
  • horus.signer.type: inproc only if no HSM/KMS is available. Plan documented to move to pkcs11 / awskms / similar.
  • Audit endpoint: set; no NoOpEmitter fallback.
  • OTel collector reachable from this host.
  • systemd unit runs as non-root vault user.
  • Bootstrap YAML stored in config-as-code repo.
  • Backend operator credentials NOT readable by the vault user (only the leaf client cert is).
  • kis vault policy lint passes against this cluster’s access rules.
  • kis vault audit verify scheduled as a CI / cron job (chain integrity).
  • Disaster-recovery drill ≤ quarterly: tear down host, restore, validate.