{"id":22216826,"url":"https://github.com/carriejv/docker-swarm-secrets","last_synced_at":"2025-07-27T14:30:56.743Z","repository":{"id":32641509,"uuid":"138654740","full_name":"carriejv/docker-swarm-secrets","owner":"carriejv","description":"A library for managing Docker secrets in Node.js, with Typescript and async/await support.","archived":false,"fork":false,"pushed_at":"2023-01-06T05:13:01.000Z","size":945,"stargazers_count":3,"open_issues_count":10,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-04T05:38:05.345Z","etag":null,"topics":["docker","docker-secrets","docker-swarm","nodejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/carriejv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-25T22:03:15.000Z","updated_at":"2023-04-11T14:21:23.000Z","dependencies_parsed_at":"2023-01-14T21:48:34.531Z","dependency_job_id":null,"html_url":"https://github.com/carriejv/docker-swarm-secrets","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/carriejv/docker-swarm-secrets","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carriejv%2Fdocker-swarm-secrets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carriejv%2Fdocker-swarm-secrets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carriejv%2Fdocker-swarm-secrets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carriejv%2Fdocker-swarm-secrets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/carriejv","download_url":"https://codeload.github.com/carriejv/docker-swarm-secrets/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/carriejv%2Fdocker-swarm-secrets/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267370435,"owners_count":24076431,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-secrets","docker-swarm","nodejs"],"created_at":"2024-12-02T22:13:43.355Z","updated_at":"2025-07-27T14:30:56.451Z","avatar_url":"https://github.com/carriejv.png","language":"TypeScript","funding_links":["https://www.paypal.me/carriejv"],"categories":[],"sub_categories":[],"readme":"# docker-swarm-secrets\n\n[![npm version](https://img.shields.io/npm/v/docker-swarm-secrets.svg)](https://www.npmjs.com/package/docker-swarm-secrets) [![npm downloads](https://img.shields.io/npm/dt/docker-swarm-secrets)](https://www.npmjs.com/package/docker-swarm-secrets) [![dependencies](https://img.shields.io/david/carriejv/docker-swarm-secrets.svg)](https://david-dm.org/carriejv/docker-swarm-secrets) [![devDependencies](https://img.shields.io/david/dev/carriejv/docker-swarm-secrets.svg)](https://david-dm.org/carriejv/docker-swarm-secrets#info=devDependencies)\n\n\n[![npm license](https://img.shields.io/npm/l/docker-swarm-secrets.svg)](https://www.npmjs.com/package/docker-sewarm-secrets) [![Build Status](https://img.shields.io/travis/carriejv/docker-swarm-secrets.svg)](https://travis-ci.org/carriejv/docker-swarm-secrets) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/carriejv) [![GitKraken](https://img.shields.io/badge/\u003c3-GitKraken-green.svg)](https://www.gitkraken.com/invite/om4Du5zG)\n\nDocker Swarm Secrets is a Node library for managing [Docker secrets](https://docs.docker.com/engine/swarm/secrets/). It aims to be a more robust and modern option than previous secret managers and includes:\n\n* Async/Await Support\n* Non-blocking File I/O\n* Extensible Automatic Secret Parsing\n* Typescript Compatability\n\nFor more information about creating and using secrets, please refer to the [Docker documentation](https://docs.docker.com/compose/compose-file/#secrets).\n\n## Docker-Swarm-Secrets is Deprecated!\n\nDocker-Swarm-Secrets has been rolled into [Technician](https://www.npmjs.com/package/technician), a brand new library that lets you manage all your application's config (secrets included!) using the familiar syntax of `docker-swarm-secrets`. This package will continue receiving security updates, but will no longer receive feature updates.\n\n[![Technician](https://img.shields.io/npm/v/technician?label=technician)](https://www.npmjs.com/package/technician)\n\n---\n\n## Migration Guide\n\nMigrating from `docker-swarm-secrets` to `technician` is easy. The biggest difference is that `technician` returns only the secret value from `read()`. The object containing the raw data Buffer is still available via `describe()`.\n\nTechnician also caches results forever by default, instead of not caching by default (a decision that was made for legacy compatability in dss).\n\n### In Docker-Swarm-Secrets:\n```ts\nimport { DSSReader } from 'docker-swarm-secrets';\n// ...\nconst secretReader = new DSSReader();\nconst mySecret = await secretReader.readSecret('mySecret');\n// mySecret === { name: 'mySecret', data: Buffer, secret: Buffer | ParsedData }\n```\n\n### In Technician:\n```ts\nimport { Technician } from 'technician';\nimport { FSConfigSource } from '@technician/fs-config-source';\n// ...\nconst technicianReader = new Technician();\n// Alternatively, your own secret mount point.\n// Technician is built to work with any files, not just secrets!\ntechnicianReader.addSource(new FSConfigSource('/run/secrets'));\nconst mySecret = await technicianReader.read('mySecret');\n// mySecret === Buffer\u003cyour file contents here\u003e\n```\n\n## Migrating Interpreters\n\nCustom interpreters are now even more flexible in `technician`! Interpreters are set at the reader level in Technician, instead of being passed in with each read. This allows for less complex typing when accessing the cache. To return multiple data types, you can still create a complex branching interpreter -- or just use multiple Technician instances.\n\nConsult the Technician docs for more information on all the new features added to interpreters.\n\nThe same `DefaultInterpreters` package is still available from Technician as well.\n\n### A Docker-Swarm-Secrets Interpreter:\n```ts\n// ...\nconst mySecret = await secretReader.readSecret('mySecret', \n    secret =\u003e secret?.data.toString('utf8')\n);\n// mySecret === { name: 'mySecret', data: Buffer, secret: string }\n```\n\n### A Technician Interpreter:\n```ts\n// ...\nconst technicianReader = new Technician(\n    secret =\u003e value: secret?.data.toString('utf8')\n);\nconst mySecret = await technicianReader.readSecret('mySecret');\n// typeof mySecret === 'string'\n```\n\n---\n\n## Installation\n\n`npm i docker-swarm-secrets`\n\nVersion `2.x.x` is compatible with Node 10 LTS and up. For compatability with prior Node releases, use the latest `1.x.x` release.\n\n## Usage\n\n### Basic Example\n```ts\nimport { DSSReader } from 'docker-swarm-secrets';\n\n// ...\n\nconst secretReader = new DSSReader();\nconst mySecret = await secretReader.readSecret('mySecret');\n/**\n * { name: 'mySecret', data: Buffer, secret: Buffer | ParsedData }\n */\n\n// or ...\n\nconst allMySecrets = await secretReader.readSecrets();\ndb.connect(allMySecrets.dbUsername.secret, allMySecrets.dbPassword.secret);\n```\n\n### Secret Parsing \u0026 Typing\n\nBy default, all valid secrets are returned as Buffers. Secrets that do not exist are returned as undefined.\n\nIf you wish to provide parsing logic for secrets, you may provide an `interpreter` function. The `secret` value of the returned object will be set to the value returned by your `interpreter` function. Typescript should infer your typing automatically.\n\n```ts\nconst myStringSecret = await secretReader.readSecret('myStringSecret', \n    secret =\u003e secret.?data.toString('utf8')\n);\nmyStringSecret.substring(0, 1); // Typescript is okay with this!\n\n// or, you can manually specify the typing ...\n\nconst myBoolSecret = await secretReader.readSecret\u003cboolean\u003e('myBoolSecret', \n    secret =\u003e secret.name === 'myBoolSecret'\n);\n```\n\nInterpreters can handle any logic necessary to get a secret into a usable state (deserialization, decryption, etc.) whenever it needs to be accessed to reduce duplication of complex parsing code.\n\n```ts\nconst mySuperComplicatedInterpreter = (secret) =\u003e {\n    // ... 10,000 lines later\n};\n// Reuse it to parse all your secrets\nconst mySuperSecretStuff = await secretReader.readSecrets(mySuperComplicatedInterpreter);\n```\n\n### Multiple Interpreters\n\nIf you need to handle a variety of secret data types, you may specify multiple interpreters with `readSecrets`.\n\nThese interpreters may have an optional `predicate`, which determines which secrets are passed to them. The first matching interpreter wins. If no interpreters match a secret, it will not be returned. A catch-all interpreter with no predicate may also be specified.\n\n```ts\nconst allMyParsedSecrets = secretReader.readSecrets([\n    { // Will only run on secrets ending in .json\n        interpreter: s =\u003e JSON.parse(s?.data.toString('utf8')),\n        predicate: s =\u003e /\\.json$/.test(s.name)\n    }, \n    { // Will match any secret\n        interpreter: s =\u003e s.?data.toString('utf8')\n    },\n]);\n```\n\n### Default Interpreters\n\nDSS provides a package of ready-to-use interpeters as `DefaultInterpreters`.\n\n```ts\nimport { DSSReader, DefaultInterpreters } from 'docker-swarm-secrets';\n\n// ...\n\n// (Default behavior if no interpreter is specified).\nconst myBufferSecret = secretReader.readSecret('secret', DefaultInterpreters.asBuffer());\n\n// Default encoding is UTF8.\nconst myStringSecret = secretReader.readSecret('secret', DefaultInterpreters.asText('utf8'));\n\n// Default encoding is UTF8. Invalid JSON will not be returned.\nconst myJSONSecret = secretReader.readSecret('secret', DefaultInterpreters.asJSON('utf8'));\n\n// Returns JSON if the text is valid JSON or plaintext if it is not.\n// This emulates the behavior of dss 1.x.x and is provided for easy migration.\n// It is substantially less efficient than using specific interpreters with predicates.\nconst legacyStyleSecret = secretReader.readSecret('secret', DefaultInterpreters.asTextOrJSON('utf8'));\n```\n\n## Synchronous Options\n\n`readSecretSync` and `readSecretsSync` are also available for synchronous code.\n\nThey are otherwise identical to the async versions.\n\n## Specifying a Mount Point\n\nIf you mount your Docker secrets at a non-default path, you may specify it as an argument to the `DSSReader` constructor.\n\nEach reader instance may only read from one secret filesystem.\n\n```ts\nconst secretReader = new DSSReader('/some/place/full/of/secrets');\n```\n\n## Migrating from `1.x.x`\n\nDocker Swarm Secrets `2.x.x` provides much more flexibility with secret reading and parsing than prior versions.\n\nIf you wish to emulate the behavior of version `1.x.x`, the following code approximates it.\n\n```ts\n// 1.x.x - Automatic JSON parsing\nconst mySecret = dss.readSecret('secret', { encoding: 'utf8', ignoreJSON: false }, (err, secret) =\u003e {\n    // ...\n});\n// 2.x.x\nconst mySecret = await secretReader.readSecret('secret', DefaultInterpreters.asTextOrJSON('utf8'));\n\n// 1.x.x - Plaintext only\nconst mySecret = dss.readSecret('secret', { encoding: 'utf8', ignoreJSON: true }, (err, secret) =\u003e {\n    // ...\n});\n// 2.x.x\nconst mySecret = await secretReader.readSecret('secret', DefaultInterpreters.asText('utf8'));\n\n```\n\n## Contributions\n\nContributions and pull requests are always welcome. Please be sure your code passes all existing tests and linting.\n\nPull requests with full code coverage are encouraged.\n\n## License\n\n[MIT](https://github.com/carriejv/docker-swarm-secrets/blob/master/LICENSE)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarriejv%2Fdocker-swarm-secrets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcarriejv%2Fdocker-swarm-secrets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcarriejv%2Fdocker-swarm-secrets/lists"}