Skip to content
Talk to our solutions team

Secrets & Security

Vault access, secret generation, hashing, encryption and certificates. Every parameter with its type, default and description, plus worked examples.

Platform-integrated secret management using HashiCorp Vault with mTLS authentication.

ParameterTypeRequiredDefaultDescription
operationstringNoreadOperation: read, get, write, set
urlstringYes-Vault server URL
clusterstringYes-Cluster name
datacenterstringYes-Datacenter name
workspacestringYes-Workspace/environment name
customerstringYes-Customer identifier
forgeslugstringYes-Forge/product slug
productiondomainstringYes-Tenant domain
certificatestringYes-TLS certificate for authentication
keystringYes-TLS private key for authentication
issuerlistYes-Certificate issuers
secretnamestringYes-Name of the secret to read/write
secretvaluestringNo-Value to write (required for write)
servicestringNovulcanService name
setvarstringNo-Variable to store result
name: vault-read
vars:
vault_url: "{{env.VAULT_URL}}"
cluster: production
datacenter: us-east-1
tasks:
- name: get-db-password
vault:
operation: read
url: "{{vault_url}}"
cluster: "{{cluster}}"
datacenter: "{{datacenter}}"
workspace: production
customer: acme
forgeslug: webapp
productiondomain: acme.example.com
certificate: "{{tls_cert}}"
key: "{{tls_key}}"
issuer:
- "{{ca_cert}}"
secretname: database-password
setvar: db_password
name: vault-write
tasks:
- name: store-api-key
vault:
operation: write
url: "{{vault_url}}"
cluster: "{{cluster}}"
datacenter: "{{datacenter}}"
workspace: production
customer: acme
forgeslug: webapp
productiondomain: acme.example.com
certificate: "{{tls_cert}}"
key: "{{tls_key}}"
issuer:
- "{{ca_cert}}"
secretname: api-key
secretvalue: "{{generated_key}}"

For simpler vault access from scripts, use the vault namespace instead of the vault task. The namespace uses the service’s pre-initialized vault client, requiring only a secret name — no TLS, datacenter, or cluster params needed:

- name: get-secret
script:
namespaces: http,vault
code: |
var secret = vault.get("database-password");
vault.save({name: "new-key", value: "value123", indefinite: true});

See vault namespace docs for full reference.

Generate secrets, passwords, and passphrases.

ParameterTypeRequiredDefaultDescription
operationstringNogenerateOperation: generate, encode, decode, hash
setvarstringYes-Variable to store result
lengthintNo32Length of generated secret
patternstringNo-Predefined pattern (see below)
wordsintNo-Number of words for passphrase
prefixstringNo-Prefix for generated secret
separatorstringNo-Word separator for passphrase
uppercaseboolNotrueInclude uppercase letters
lowercaseboolNotrueInclude lowercase letters
digitsboolNotrueInclude digits
specialboolNofalseInclude special characters
charsetstringNo-Custom character set
hashboolNofalseAlso generate bcrypt hash
valuestringNo-Input value for encode/decode/hash
encodingstringNobase64Encoding: base64, base64url, hex
PatternDescription
alphanumericLetters and digits
alphaLetters only
numericDigits only
hexHexadecimal
base64Base64-safe characters
passwordStrong password with all character types
passphraseDiceware word-based password
pinNumeric PIN
uuidUUID v4 format
apikeyAPI key format (prefix_random)
name: secret-apikey
tasks:
- name: generate
secret:
length: 32
setvar: api_key
name: secret-passphrase
tasks:
- name: generate
secret:
pattern: passphrase
words: 4
setvar: memorable_password
## Result: "correct-horse-battery-staple"
name: secret-password
tasks:
- name: generate
secret:
pattern: password
length: 16
hash: true
setvar: user_password
## Result: {{user_password}} = "Kj#9mN$pL2@xQw4r"
## {{user_password_hash}} = bcrypt hash
name: secret-prefixed
tasks:
- name: generate
secret:
pattern: apikey
prefix: sk_live
length: 32
setvar: stripe_key
## Result: "sk_live_a1b2c3d4e5f6..."
name: secret-encode
vars:
username: admin
password: secret
tasks:
- name: encode
secret:
operation: encode
encoding: base64
value: "{{username}}:{{password}}"
setvar: basic_auth

Secret generation and encoding functions.

FunctionDescription
secret.generate()Generate random secrets/passwords
secret.encode()Encode data (base64, hex)
secret.decode()Decode encoded data
secret.hash()Hash value using bcrypt
secret.validate()Validate password strength
ParameterTypeDefaultDescription
patternstring"alphanumeric"Pattern: alphanumeric, hex, base64, passphrase
lengthint32Secret length
prefixstring-Prefix to add
uppercaseboolfalseInclude uppercase
lowercaseboolfalseInclude lowercase
digitsboolfalseInclude digits
specialboolfalseInclude special chars
charsetstring-Custom character set
hashboolfalseReturn bcrypt hash too
separatorstring"-"Word separator (passphrase)
wordsint-Word count (passphrase)
ParameterTypeDefaultDescription
datastring-Data to encode/decode
encodingstring"base64"Encoding: base64, base32, hex
// Generate API key
let key = secret.generate({
length: 32,
pattern: "alphanumeric"
})
log("API Key:", key.secret)
// Generate passphrase
let pass = secret.generate({
pattern: "passphrase",
words: 4,
separator: "-"
})
log("Passphrase:", pass.secret)
// Generate with hash
let pwd = secret.generate({
length: 16,
special: true,
hash: true
})
log("Password:", pwd.secret)
log("Hash:", pwd.hash)
// Base64 encode
let encoded = secret.encode({
data: "admin:password",
encoding: "base64"
})
log("Encoded:", encoded.encoded)
// Base64 decode
let decoded = secret.decode({
data: encoded.encoded,
encoding: "base64"
})
log("Decoded:", decoded.decoded)
// Hash password (bcrypt)
let hashed = secret.hash({
value: "mypassword"
})
log("Bcrypt hash:", hashed.hash)
// Validate password strength
let valid = secret.validate({
value: "WeakPwd"
})
if (!valid.success) {
log("Password too weak:", valid.error)
}

File encryption using AES.

ParameterTypeRequiredDescription
secretstringYesEncryption key (vault key)
sourcestringYesSource file path
destinationstringYesDestination file path
patternstringNoGlob pattern for multiple files
name: encrypt-file
tasks:
- name: encrypt
encrypt:
secret: my-vault-key
source: /data/file.txt
destination: /data/file.enc
name: decrypt-file
tasks:
- name: decrypt
decrypt:
secret: my-vault-key
source: /data/file.enc
destination: /data/file.txt

Encryption and decryption functions.

FunctionDescription
crypt.encryptFile()Encrypt a file
crypt.decryptFile()Decrypt a file
crypt.encrypt()Encrypt data in memory
crypt.decrypt()Decrypt data in memory
ParameterTypeDefaultDescription
secretstring-Encryption key/passphrase
sourcestring-Source file path
destinationstring-Destination file path
algorithmstring"aes-256-gcm"Algorithm: aes-256-gcm, aes-256-cbc, aes-128-gcm
overwriteboolfalseOverwrite existing file
iterationsint100000PBKDF2 iterations
ParameterTypeDefaultDescription
secretstring-Encryption key/passphrase
datastring-Data to encrypt/decrypt
algorithmstring"aes-256-gcm"Algorithm
iterationsint100000PBKDF2 iterations
// Encrypt file
let result = crypt.encryptFile({
secret: "my-secret-key",
source: "/data/sensitive.txt",
destination: "/data/sensitive.enc",
algorithm: "aes-256-gcm"
})
log("Encrypted to:", result.destination)
// Decrypt file
crypt.decryptFile({
secret: "my-secret-key",
source: "/data/sensitive.enc",
destination: "/data/sensitive.txt",
overwrite: true
})
// Encrypt data in memory (returns base64)
let encrypted = crypt.encrypt({
secret: "my-secret-key",
data: "sensitive information"
})
log("Encrypted:", encrypted.encrypted)
// Decrypt data in memory
let decrypted = crypt.decrypt({
secret: "my-secret-key",
data: encrypted.encrypted
})
log("Decrypted:", decrypted.decrypted)
// Higher security with more iterations
crypt.encryptFile({
secret: "my-secret-key",
source: "/data/critical.txt",
destination: "/data/critical.enc",
iterations: 500000
})

Generate cryptographic hashes.

ParameterTypeRequiredDefaultDescription
valuestringNo-String to hash
filestringNo-File to hash
algorithmstringNosha256Algorithm: sha256, sha512, sha1, md5
lengthintNo0Truncate hash to N characters
setstringYes-Variable to store hash
name: hash-string
tasks:
- name: hash
hash:
value: "hello world"
algorithm: sha256
set: hash_result
name: hash-file
tasks:
- name: hash-file
hash:
file: /path/to/file.txt
algorithm: sha256
set: file_hash

Cryptographic hashing functions.

FunctionDescription
hash.string()Hash a string value
hash.file()Hash a file
hash.bytes()Hash byte data
ParameterTypeDefaultDescription
datastring-Data to hash (for string/bytes)
pathstring-File path (for file)
algorithmstring"sha256"Algorithm: sha256, sha512, sha1, md5, blake2b, xxhash
lengthint0Truncate hash to N characters (0 = full)
// Hash a string
let result = hash.string({
data: "hello world",
algorithm: "sha256"
})
log("Hash:", result.hash)
// Hash with truncation
let short = hash.string({
data: "hello world",
algorithm: "sha256",
length: 8
})
log("Short hash:", short.hash)
// Hash a file
let fileHash = hash.file({
path: "/path/to/file.txt",
algorithm: "sha256"
})
log("File hash:", fileHash.hash)
// Different algorithms
hash.string({ data: "test", algorithm: "md5" }) // MD5
hash.string({ data: "test", algorithm: "sha512" }) // SHA-512
hash.string({ data: "test", algorithm: "blake2b" }) // BLAKE2b
hash.string({ data: "test", algorithm: "xxhash" }) // xxHash (fast)

Generate unique identifiers (ULID, UUID, NanoID, KSUID, XID).

ParameterTypeRequiredDefaultDescription
typestringNoulidID type (see below)
setvarstringYes-Variable to store generated ID
TypeDescription
ulidULID (uppercase)
ulid-lowerULID (lowercase)
uuidUUID v4
uuidv4UUID v4
uuidv6UUID v6
uuidv7UUID v7
uuidv1UUID v1
name: gen-id
tasks:
- name: create-id
id:
type: uuidv7
setvar: user_id
name: gen-ulid
tasks:
- name: create-ulid
id:
setvar: request_id

Identifier generation functions (ULID, UUID).

FunctionDescription
id.generate()Generate unique identifier(s)
ParameterTypeDefaultDescription
typestring"ulid"ID type: ulid, uuid, nanoid, ksuid, xid
countint1Number of IDs to generate
// Generate single ULID (default)
let result = id.generate({})
log("ID:", result.id)
// Generate UUID v4
let uuid = id.generate({ type: "uuid" })
log("UUID:", uuid.id)
// Generate multiple IDs
let ids = id.generate({
type: "nanoid",
count: 5
})
log("Generated", ids.ids.length, "IDs")
// Available types
id.generate({ type: "ulid" }) // 01ARZ3NDEKTSV4RRFFQ69G5FAV
id.generate({ type: "uuid" }) // f47ac10b-58cc-4372-a567-0e02b2c3d479
id.generate({ type: "nanoid" }) // V1StGXR8_Z5jdHi6B-myT
id.generate({ type: "ksuid" }) // 0ujsswThIGTUYm2K8FjOOfXtY1K
id.generate({ type: "xid" }) // 9m4e2mr0ui3e8a215n4g

ACME certificate management — issue, renew, revoke, read, list.

Default CA is Let’s Encrypt; the caURL parameter accepts any ACME-compatible directory (ZeroSSL, step-ca, Buypass). Built on certmagic — supports HTTP-01, DNS-01, and TLS-ALPN-01 challenges. DNS-01 reuses the six libdns providers wired into the dns task.

This task replaces the lego-based acme task entirely. The old acme:/legodns: names are gone. The lego dependency is dropped along with its 181 transitively-imported DNS providers — net binary savings of 30–50 MB.

FieldTypeRequiredDefaultDescription
opstringNoobtainobtain / renew / revoke / info / list
caURLstringNoLE productionACME directory URL; shortcuts: letsencrypt, staging, zerossl
emailstringYes (obtain/renew/revoke)Account contact email
storagestringNo$XDG_DATA_HOME/letsencryptFilesystem path
keyTypestringNoECDSA-P256ECDSA-P256 / ECDSA-P384 / RSA-2048 / RSA-4096 / ED25519
timeoutdurationNoWall-clock cap
setvarstringNoCapture result map into a workflow variable
FieldTypeRequiredDefaultDescription
challengestringNodns-01Challenge type
mustStapleboolNofalseOCSP must-staple

DNS-01 fields: dnsProvider, dnsCredentials (same shape as the dns task), dnsPropagation, dnsResolvers.

HTTP-01 fields: httpAddress (default :80).

TLS-ALPN-01 fields: tlsAddress (default :443).

obtain / renew / info populate cert; list populates certs. Both shapes carry: domains, notBefore, notAfter, issuer, serial, fingerprint, daysRemaining, certPath, keyPath, fullchainPath.

revoke: { success, error }.

- name: cert
letsencrypt:
op: obtain
storage: /var/lib/letsencrypt
domains:
- example.com
- www.example.com
- api.example.com
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials:
api_token: "{{ cf_token }}"
setvar: cert
- name: cert
letsencrypt:
op: obtain
caURL: staging
domains: ["dev.example.com"]
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }
HTTP-01 (host directly reachable on port 80)
Section titled “HTTP-01 (host directly reachable on port 80)”
- name: cert
letsencrypt:
op: obtain
domains: ["app.example.com"]
challenge: http-01
- name: renew
letsencrypt:
op: renew
domains: ["example.com", "www.example.com"]
force: true
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }
Read existing cert without touching the CA
Section titled “Read existing cert without touching the CA”
- name: info
letsencrypt:
op: info
storage: /var/lib/letsencrypt
domain: www.example.com
setvar: cert
- name: report
print:
message: "expires in {{ cert.cert.daysRemaining }} days"
- name: revoke
letsencrypt:
op: revoke
domain: oops.example.com
reason: 1 # keyCompromise (RFC 5280)
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }

Same five verbs under the letsencrypt script namespace.

let result = letsencrypt.obtain({
storage: "/var/lib/letsencrypt",
domains: ["example.com", "www.example.com"],
challenge: "dns-01",
dnsProvider: "cloudflare",
dnsCredentials: { api_token: cfToken }
})
log("cert at " + result.cert.certPath)

See docs/namespaces/letsencrypt.md for full reference.