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.
1. Prerequisites
Section titled “1. Prerequisites”| Requirement | Detail |
|---|---|
| OS | Linux x86_64 / arm64. macOS supported for dev only. |
| Privileged user | Service runs as vault. Do not run as root. |
| Backend storage | A 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). |
| Filesystem | A persistent local directory for state and cert material (default /var/lib/vault, /etc/vault). |
| Network | One TCP port (default :7999). Outbound to the backend (HCP: 8200; etc.). Outbound HTTPS to Chitragupta (audit.svc, typically :8443) for audit submission. |
| TLS material | mTLS 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. |
| Time | NTP-synced. JWT nbf/exp and cert validity windows assume reasonable wall-clock accuracy. |
2. Install
Section titled “2. Install”2.1 From a release tarball
Section titled “2.1 From a release tarball”sudo install -d -o root -g root /opt/vaultsudo tar -C /opt/vault -xzf vault.svc-${VERSION}-linux-amd64.tar.gzsudo install -d -o root -g vault -m 0750 /etc/vaultsudo install -d -o vault -g vault -m 0700 /var/lib/vaultsudo install -d -o root -g vault -m 0750 /etc/vault/certs2.2 systemd unit
Section titled “2.2 systemd unit”[Unit]Description=vault.svc trust plane (kis Vault server)After=network.target
[Service]Type=simpleUser=vaultGroup=vaultExecStart=/opt/vault/vault.svc server -f /etc/vault/vault.yamlRestart=on-failureRestartSec=2LimitNOFILE=65536
# Hardening — single-node, no shared FS:ProtectSystem=strictProtectHome=trueReadWritePaths=/var/lib/vault /var/log/vaultNoNewPrivileges=truePrivateTmp=trueLockPersonality=trueRestrictSUIDSGID=true
# Resource limits.MemoryMax=1GTasksMax=256
[Install]WantedBy=multi-user.targetsudo systemctl daemon-reloadsudo systemctl enable --now vault.svc3. Bootstrap YAML — single-node
Section titled “3. Bootstrap YAML — single-node”Generate a template:
sudo /opt/vault/vault.svc config generate bootstrap > /etc/vault/vault.yaml# Or pick a specific shape:sudo /opt/vault/vault.svc config listEdit /etc/vault/vault.yaml. Production-style example using HCP Vault
(works against OpenBao identically — swap hcpvault → openbao and
the cert paths):
# Service identity — chassis convention.service: vaultversion: 1.0.0sid: ${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 }3.1 Templates available
Section titled “3.1 Templates available”vault.svc config list # list allvault.svc config generate bootstrap # HCP + inproc + JS rulesvault.svc config generate bootstrap-dev # FsVault (dev only)vault.svc config generate backend-openbao # OpenBao snippetvault.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 samplevault.svc config generate agent # reference per-node agent config4. Backend setup (HCP Vault / OpenBao)
Section titled “4. Backend setup (HCP Vault / OpenBao)”A one-time bootstrap of the backend, per the release documentation. Summary:
vault operator init(orbao operator init), unseal with the issued keys, store the root token offline.vault auth enable cert— turn on certificate auth.- Write the kisai-policy granting access to
secret/*andkisaicerts/*. vault write auth/cert/certs/vault-cert display_name=vault_cert policies=kisai-policy certificate=@/etc/vault/certs/vault-client.crtvault secrets enable -path=secret kv-v2vault 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.
5. TLS material
Section titled “5. TLS material”For any non-loopback deployment, two cert pairs:
| Pair | Purpose | Where |
|---|---|---|
| Server cert | Terminates incoming mTLS from consumers / operator | host/port listener |
| Vault client cert | Authenticates vault.svc to HCP/OpenBao | vaultmanager.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.
# Lock down permssudo chown -R root:vault /etc/vault/certssudo chmod -R 0640 /etc/vault/certs/*.keysudo chmod 0644 /etc/vault/certs/*.crt6. First boot
Section titled “6. First boot”sudo systemctl start vault.svcsudo systemctl status vault.svcVerify:
curl -s http://localhost:7999/version # unauthcurl -s http://localhost:7999/ready # 200 → readycurl -s --cert client.crt --key client.key --cacert ca.crt \ https://localhost:7999/certificate/internal/issuerTail logs:
journalctl -u vault.svc -fLook for successfully connected to vault backend hcpvault (or your
backend’s name) within 2 s of start.
7. Day-2 operations
Section titled “7. Day-2 operations”7.1 Operator commands via the CLI
Section titled “7.1 Operator commands via the CLI”From any host with the kis CLI:
kis vault status --server https://vault.example.com:7999kis vault audit query --since 1hkis vault node-token issue --scope dc=us-west,cluster=prodOperator 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)”kis vault node-token issue \ --scope dc=us-west,cluster=prod \ --ttl 1h \ --uses 1# → hj_v1_n8x2k_a1b2c3d4e5f6g7h8j9k0Give the printed token to the operator running vault-agent init on
the new node. See the agent guide.
7.3 Inspecting the audit chain
Section titled “7.3 Inspecting the audit chain”kis vault audit query --since 24h --actor 'spiffe://kis.ai/customer/acme/...'kis vault audit verify # walks the chain from genesisaudit verify is slow (whole-chain replay); run it as a periodic CI
job rather than interactively.
7.4 Rotating an API-key-style secret
Section titled “7.4 Rotating an API-key-style secret”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.
8. Backup & restore
Section titled “8. Backup & restore”8.1 What to back up
Section titled “8.1 What to back up”Two stores:
-
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.
-
Data API audit + entity tables —
vault.svcwrites 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.
8.2 Restoring after host loss
Section titled “8.2 Restoring after host loss”- Provision a new host, same OS, same package install (§2).
- Copy
/etc/vault/vault.yamland/etc/vault/certs/*from config-as-code (your cluster repository). sudo systemctl start vault.svc.- Verify
/readyreturns 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.
9. Upgrade
Section titled “9. Upgrade”sudo systemctl stop vault.svcsudo tar -C /opt/vault -xzf vault.svc-${NEW_VERSION}-linux-amd64.tar.gzsudo systemctl start vault.svcDowntime: 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.
10. Troubleshooting
Section titled “10. Troubleshooting”| Symptom | Likely cause | Action |
|---|---|---|
/ready returns 503 | Backend 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 listener | Server 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 logs | The cert role lacks auth/token/renew-self permission. | Re-apply kisai-policy on the backend. |
| Audit emission failing | Chitragupta 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 examples | Broken 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. |
11. Failure modes
Section titled “11. Failure modes”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.
12. Hardening checklist
Section titled “12. Hardening checklist”- All TLS material has
not_after:≤ 12 months. Rotation schedule documented. -
vault.client.transportset 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: inproconly if no HSM/KMS is available. Plan documented to move topkcs11/awskms/ similar. - Audit
endpoint:set; no NoOpEmitter fallback. - OTel collector reachable from this host.
- systemd unit runs as non-root
vaultuser. - Bootstrap YAML stored in config-as-code repo.
- Backend operator credentials NOT readable by the
vaultuser (only the leaf client cert is). -
kis vault policy lintpasses against this cluster’s access rules. -
kis vault audit verifyscheduled as a CI / cron job (chain integrity). - Disaster-recovery drill ≤ quarterly: tear down host, restore, validate.