@akeyless-community/digitalocean-runtime
v0.1.0
Published
Fetch Akeyless secrets at runtime on DigitalOcean App Platform (Node.js) — no env-var sync required
Maintainers
Readme
@akeyless-community/digitalocean-runtime
Fetch Akeyless secrets at runtime on DigitalOcean App Platform (Node.js). Application secrets stay in Akeyless — only bootstrap auth variables are stored on DigitalOcean.
Repository: github.com/akeyless-community/digitalocean-runtime
Install
npm install @akeyless-community/digitalocean-runtimeRequires Node.js 18+.
Quick start
1. Set bootstrap variables on App Platform
In your component Environment Variables (runtime scope), add read-only Akeyless credentials:
| Variable | Required | Example |
|----------|----------|---------|
| AKEYLESS_ACCESS_ID | Yes* | p-xxxxx |
| AKEYLESS_ACCESS_KEY | Yes* | access key secret |
| AKEYLESS_SECRET_PREFIX | Recommended | /digitalocean/my-app/production |
| AKEYLESS_GATEWAY_URL | No | https://api.akeyless.io |
* Or use another auth method below.
Bindable variables for prefix derivation — App Platform does not inject these automatically; add them as runtime variables using bindable references:
| Variable | Value (bindable) | Purpose |
|----------|------------------|---------|
| APP_DOMAIN | ${APP_DOMAIN} | Human-readable app slug for secret paths |
| APP_ID | ${APP_ID} | Fallback app identifier |
| AKEYLESS_ENV | production (or staging, etc.) | Environment segment in paths |
If AKEYLESS_SECRET_PREFIX is omitted, the library derives it from:
/digitalocean/{APP_DOMAIN or APP_ID}/{AKEYLESS_ENV}Set AKEYLESS_APP_NAME to override the app segment when your domain is not ideal for paths.
2. Store application secrets in Akeyless
/digitalocean/my-app/production/DATABASE_URL
/digitalocean/my-app/production/STRIPE_SECRET_KEYFor multi-component apps, opt into per-component prefixes:
DO_COMPONENT_NAME=web
AKEYLESS_INCLUDE_COMPONENT_IN_PREFIX=true
# → /digitalocean/my-app/production/web/DATABASE_URLDO_COMPONENT_NAME should match the name field of your service/worker in the app spec.
3. Fetch secrets in your app
const express = require('express');
const { getSecret } = require('@akeyless-community/digitalocean-runtime');
const app = express();
app.get('/health', async (_req, res) => {
const dbUrl = await getSecret('DATABASE_URL');
res.json({ ok: true, hasDb: Boolean(dbUrl) });
});
app.listen(process.env.PORT || 8080);Use getSecret only in server code. Never expose fetched secrets to the browser.
App spec example
name: my-app
services:
- name: web
github:
repo: your-org/your-repo
branch: main
envs:
- key: AKEYLESS_ACCESS_ID
scope: RUN_TIME
value: p-xxxxx
- key: AKEYLESS_ACCESS_KEY
scope: RUN_TIME
type: SECRET
value: your-access-key
- key: APP_DOMAIN
scope: RUN_TIME
value: ${APP_DOMAIN}
- key: AKEYLESS_ENV
scope: RUN_TIME
value: productionPer-environment prefixes
DigitalOcean does not provide a built-in environment tier name. Set AKEYLESS_ENV per deployment (or use separate apps):
| Deployment | AKEYLESS_ENV | Typical prefix |
|------------|----------------|----------------|
| Production | production | /digitalocean/my-app/production |
| Staging | staging | /digitalocean/my-app/staging |
Set AKEYLESS_SECRET_PREFIX explicitly when you need a custom layout.
API
Convenience (singleton, container-friendly)
const { getSecret, getDefaultClient } = require('@akeyless-community/digitalocean-runtime');
const dbUrl = await getSecret('DATABASE_URL');Explicit client
const { createClient } = require('@akeyless-community/digitalocean-runtime');
const client = createClient({
gatewayUrl: 'https://api.akeyless.io',
secretPrefix: '/digitalocean/my-app/production',
accessId: process.env.AKEYLESS_ACCESS_ID,
accessKey: process.env.AKEYLESS_ACCESS_KEY,
});
await client.getSecret('DATABASE_URL');
await client.getSecretAtPath('/custom/full/path');
await client.getDynamicSecret('db-creds');
await client.getRotatedSecret('rotated-api-key');Authentication
Configure via App Platform environment variables or createClient({ ... }).
| Method | AKEYLESS_ACCESS_TYPE | Additional variables |
|--------|------------------------|----------------------|
| Access key (default) | access_key | AKEYLESS_ACCESS_ID, AKEYLESS_ACCESS_KEY |
| API key | api_key | AKEYLESS_ACCESS_ID, AKEYLESS_ACCESS_KEY |
| Universal Identity | universal_identity | AKEYLESS_UID_TOKEN |
| JWT | jwt | AKEYLESS_ACCESS_ID, AKEYLESS_JWT |
| AWS IAM | aws_iam | AKEYLESS_ACCESS_ID, optional AKEYLESS_CLOUD_ID |
| Pre-authenticated | — | AKEYLESS_TOKEN |
Use a dedicated Akeyless auth method with read-only access to your /digitalocean/... path.
Local development
Export the same variables you use on App Platform:
export AKEYLESS_ACCESS_ID=p-xxxxx
export AKEYLESS_ACCESS_KEY=your-key
export AKEYLESS_APP_NAME=my-app
export AKEYLESS_ENV=development
export AKEYLESS_SECRET_PREFIX=/digitalocean/my-app/developmentOr use doctl apps dev when available in your workflow.
Caching
- Auth tokens refresh before expiry (default margin: 1 minute).
- Secret values cache in memory for 5 minutes by default (
AKEYLESS_SECRET_CACHE_TTL_MS). - Long-lived containers reuse the module singleton.
Lower TTL or use ignoreCache: true for frequently rotated secrets.
Push sync vs runtime pull
| Pattern | When to use | |---------|-------------| | Runtime pull (this package) | Akeyless stays source of truth; only bootstrap creds on App Platform | | Push sync | Copy secrets into App Platform variables (future Akeyless Destination Sync or CI) |
Runtime pull works today without a DigitalOcean marketplace listing.
Example app
npm run build
cd examples/express && npm install
npm startSet AKEYLESS_* env vars before starting.
Publishing
This package is Apache-2.0 and published as @akeyless-community/digitalocean-runtime on npm.
npm ci
npm test
npm publish --access publicRelated community projects
- @akeyless-community/railway-runtime — Railway runtime secrets
- @akeyless-community/fly-runtime — Fly.io runtime secrets
- @akeyless-community/vercel-runtime — Vercel runtime secrets
- @akeyless-community/netlify-runtime — Netlify runtime secrets
- @akeyless-community/heroku-runtime — Heroku runtime secrets
License
Apache-2.0
