Environment Variables
Environment variables are key-value pairs that change how your content behaves at runtime.
You set them in the ricochet UI or through the REST API.
During development you may keep secrets in a .Renviron or .env file.
These files should not be deployed with your content item, and the ricochet CLI leaves them out of a deployment.
Ricochet encrypts environment variables at rest and decrypts them only before it starts a process.
Any change to an environment variable stops all running instances, so future requests use the new value.
To read a value from HashiCorp Vault, OpenBao or Azure Key Vault instead of storing it in ricochet, see Integrations.
Using the UI
Section titled “Using the UI”Open your content item and select the “Environment Variables” tab. Here you can add or remove environment variables.
The Key is the name of the environment variable.
Value is its value.
Press ”+ Add Variable” to save the environment variable.
New processes get the new environment variables.
Using the REST API
Section titled “Using the REST API”No value is ever sent in plain text. You must encrypt both the names and the values before you send them to the API. To do this, fetch the server’s public key, RSA encrypt each name and value with it, and put the results in the JSON body.
# fetch the server's public keycurl -s https://try.ricochet.rs/api/v0/public-key -o ricochet.pub
# encrypt one name or valueencrypt() { printf '%s' "$1" | openssl pkeyutl -encrypt -pubin -inkey ricochet.pub \ -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256 | openssl base64 -A}
# add or update ENV_NAME and leave the other variables in placecurl -X PATCH \ 'https://try.ricochet.rs/api/v0/content/01JSZAXZ3TSTAYXP56ARDVFJCJ/env-vars' \ -H 'Authorization: Key rico_xxxxx' \ -H 'Content-Type: application/json' \ -d "{\"$(encrypt ENV_NAME)\": \"$(encrypt ENV_VALUE)\"}"The encrypt function above handles names and values up to 190 bytes.
For a longer value, such as a service account key, use one of these functions.
Each returns the encrypted name and value to send in the JSON body.
encrypt <- function(key, value, host = "https://try.ricochet.rs") { pub_key <- httr2::request(host) |> httr2::req_url_path_append("/api/v0/public-key") |> httr2::req_perform() |> httr2::resp_body_string() |> openssl::read_pubkey()
# encrypt the key key_encrypted <- b64::encode( openssl::rsa_encrypt( charToRaw(key), pub_key ) ) # encrypt the value key <- openssl::rand_bytes(32) nonce <- openssl::rand_bytes(12) sealed <- c(nonce, openssl::aes_gcm_encrypt(charToRaw(value), key, nonce)) wrapped <- openssl::rsa_encrypt(key, pub_key) value <- sprintf( "v2:%s:%s", openssl::base64_encode(wrapped), openssl::base64_encode(sealed) )
list(key = key_encrypted, value = value)}
encrypt("key", "value")using HTTP, Base64, Random, OpenSSL_jll
function rsa_encrypt(data, pem) path, io = mktemp() write(io, pem) close(io) cmd = `$(openssl()) pkeyutl -encrypt -pubin -inkey $path -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha256` read(pipeline(IOBuffer(data), cmd))end
function aes_gcm_encrypt(data, key, nonce) ctx = ccall((:EVP_CIPHER_CTX_new, libcrypto), Ptr{Cvoid}, ()) cipher = ccall((:EVP_aes_256_gcm, libcrypto), Ptr{Cvoid}, ()) ccall((:EVP_EncryptInit_ex, libcrypto), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{UInt8}, Ptr{UInt8}), ctx, cipher, C_NULL, key, nonce) out = Vector{UInt8}(undef, length(data)) len = Ref{Cint}() ccall((:EVP_EncryptUpdate, libcrypto), Cint, (Ptr{Cvoid}, Ptr{UInt8}, Ref{Cint}, Ptr{UInt8}, Cint), ctx, out, len, data, length(data)) ccall((:EVP_EncryptFinal_ex, libcrypto), Cint, (Ptr{Cvoid}, Ptr{UInt8}, Ref{Cint}), ctx, pointer(out, len[] + 1), len) tag = Vector{UInt8}(undef, 16) # 0x10 is EVP_CTRL_GCM_GET_TAG ccall((:EVP_CIPHER_CTX_ctrl, libcrypto), Cint, (Ptr{Cvoid}, Cint, Cint, Ptr{UInt8}), ctx, 0x10, 16, tag) ccall((:EVP_CIPHER_CTX_free, libcrypto), Cvoid, (Ptr{Cvoid},), ctx) vcat(out, tag)end
function encrypt(key, value; host = "https://try.ricochet.rs") pem = String(HTTP.get("$host/api/v0/public-key").body)
# encrypt the key key_encrypted = base64encode(rsa_encrypt(key, pem))
# encrypt the value aes_key = rand(RandomDevice(), UInt8, 32) nonce = rand(RandomDevice(), UInt8, 12) sealed = vcat(nonce, aes_gcm_encrypt(Vector{UInt8}(value), aes_key, nonce)) wrapped = rsa_encrypt(aes_key, pem) value = "v2:$(base64encode(wrapped)):$(base64encode(sealed))"
Dict("key" => key_encrypted, "value" => value)end
encrypt("key", "value")import base64, osfrom urllib.request import urlopenfrom cryptography.hazmat.primitives import hashes, serializationfrom cryptography.hazmat.primitives.asymmetric import paddingfrom cryptography.hazmat.primitives.ciphers.aead import AESGCM
def encrypt(key, value, host="https://try.ricochet.rs"): pub_key = serialization.load_pem_public_key(urlopen(f"{host}/api/v0/public-key").read()) oaep = padding.OAEP(mgf=padding.MGF1(hashes.SHA256()), algorithm=hashes.SHA256(), label=None)
# encrypt the key key_encrypted = base64.b64encode(pub_key.encrypt(key.encode(), oaep)).decode()
# encrypt the value aes_key = AESGCM.generate_key(bit_length=256) nonce = os.urandom(12) sealed = nonce + AESGCM(aes_key).encrypt(nonce, value.encode(), None) wrapped = pub_key.encrypt(aes_key, oaep) value = f"v2:{base64.b64encode(wrapped).decode()}:{base64.b64encode(sealed).decode()}"
return {"key": key_encrypted, "value": value}
encrypt("key", "value")Every endpoint expects encrypted environment variables.
| Method | Path | Effect |
|---|---|---|
GET | /api/v0/content/{id}/env-vars | List the names |
PATCH | /api/v0/content/{id}/env-vars | Add or update the variables sent and keep the rest |
PUT | /api/v0/content/{id}/env-vars | Replace the whole set and delete anything not sent |
DELETE | /api/v0/content/{id}/env-vars/{name} | Remove one variable |
You cannot read the raw values through the API.
The GET endpoint returns only the names of the keys.
API reference
Section titled “API reference”Limitations
Section titled “Limitations”A name may be at most 190 bytes and a value at most 64 KiB.
Keys may only consist of ASCII letters, numbers, and underscores.
Accessing environment variables
Section titled “Accessing environment variables”To read an environment variable in R, use Sys.getenv("KEY_NAME").
In Julia, use the built-in dictionary ENV["KEY_NAME"].