mirror of
				https://git.coolaj86.com/coolaj86/greenlock-store-fs.js.git
				synced 2025-11-04 11:02:47 +00:00 
			
		
		
		
	update docs
This commit is contained in:
		
							parent
							
								
									e0a9fff07d
								
							
						
					
					
						commit
						5490a194eb
					
				
							
								
								
									
										263
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										263
									
								
								README.md
									
									
									
									
									
								
							@ -12,125 +12,180 @@ Works with all ACME (Let's Encrypt) SSL certificate sytles:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# Usage
 | 
					# Usage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Global** config:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
var greenlock = require('greenlock');
 | 
					greenlock.manager.defaults({
 | 
				
			||||||
var gl = greenlock.create({
 | 
					    store: {
 | 
				
			||||||
  configDir: '~/.config/acme'
 | 
					        module: "greenlock-store-fs",
 | 
				
			||||||
, store: require('greenlock-store-fs')
 | 
					        basePath: "~/.config/greenlock"
 | 
				
			||||||
, approveDomains: approveDomains
 | 
					    }
 | 
				
			||||||
, ...
 | 
					});
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Per-site** config:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					greenlock.add({
 | 
				
			||||||
 | 
					    subject: "example.com",
 | 
				
			||||||
 | 
					    altnames: ["example.com", "www.example.com"],
 | 
				
			||||||
 | 
					    store: {
 | 
				
			||||||
 | 
					        module: "greenlock-store-fs",
 | 
				
			||||||
 | 
					        basePath: "~/.config/greenlock"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# File System
 | 
					# File System
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The default file system layout mirrors that of le-store-certbot in order to make transitioning effortless,
 | 
					The default file system layout mirrors that of certbot (python Let's Encrypt implementation) and
 | 
				
			||||||
in most situations:
 | 
					the prior le-store-certbot in order to make transitioning effortless.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					The default structure looks like this:
 | 
				
			||||||
acme
 | 
					
 | 
				
			||||||
├── accounts
 | 
					```txt
 | 
				
			||||||
│   └── acme-staging-v02.api.letsencrypt.org
 | 
					.config
 | 
				
			||||||
│       └── directory
 | 
					└── greenlock
 | 
				
			||||||
│           └── sites@example.com.json
 | 
					    ├── accounts
 | 
				
			||||||
└── live
 | 
					    │   └── acme-staging-v02.api.letsencrypt.org
 | 
				
			||||||
    ├── example.com
 | 
					    │       └── directory
 | 
				
			||||||
    │   ├── bundle.pem
 | 
					    │           └── sites@example.com.json
 | 
				
			||||||
    │   ├── cert.pem
 | 
					    ├── staging
 | 
				
			||||||
    │   ├── chain.pem
 | 
					    │   └── (same as live)
 | 
				
			||||||
    │   ├── fullchain.pem
 | 
					    └── live
 | 
				
			||||||
    │   └── privkey.pem
 | 
					        ├── example.com
 | 
				
			||||||
    └── www.example.com
 | 
					        │   ├── bundle.pem
 | 
				
			||||||
        ├── bundle.pem
 | 
					        │   ├── cert.pem
 | 
				
			||||||
        ├── cert.pem
 | 
					        │   ├── chain.pem
 | 
				
			||||||
        ├── chain.pem
 | 
					        │   ├── fullchain.pem
 | 
				
			||||||
        ├── fullchain.pem
 | 
					        │   └── privkey.pem
 | 
				
			||||||
        └── privkey.pem
 | 
					        └── www.example.com
 | 
				
			||||||
 | 
					            ├── bundle.pem
 | 
				
			||||||
 | 
					            ├── cert.pem
 | 
				
			||||||
 | 
					            ├── chain.pem
 | 
				
			||||||
 | 
					            ├── fullchain.pem
 | 
				
			||||||
 | 
					            └── privkey.pem
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Wildcards & AltNames
 | 
					# Internal Implementation Details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Working with wildcards and multiple altnames requires greenlock >= v2.7 (or v3).
 | 
					You **DO NOT NEED TO KNOW** these details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
To do so you must return `{ subject: '...', altnames: ['...', ...] }` within the `approveDomains()` callback.
 | 
					They're provided for the sake of understanding what happens "under the hood"
 | 
				
			||||||
 | 
					to help you make better choices "in the seat".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`subject` refers to "the subject of the ssl certificate" as opposed to `domain` which indicates "the domain servername
 | 
					# Parameters
 | 
				
			||||||
used in the current request". For single-domain certificates they're always the same, but for multiple-domain
 | 
					 | 
				
			||||||
certificates `subject` must be the name no matter what `domain` is receiving a request. `subject` is used as
 | 
					 | 
				
			||||||
part of the name of the file storage path where the certificate will be saved (or retrieved).
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
`altnames` should be the list of SubjectAlternativeNames (SANs) on the certificate.
 | 
					| parameters        | example                                                  | notes            |
 | 
				
			||||||
The subject and the first altname must be an exact match: `subject === altnames[0]`.
 | 
					| ----------------- | -------------------------------------------------------- | ---------------- |
 | 
				
			||||||
 | 
					| `env`             | `staging` or `live`                                      | -                |
 | 
				
			||||||
 | 
					| `directoryUrl`    | `https://acme-staging-v02.api.letsencrypt.org/directory` | -                |
 | 
				
			||||||
 | 
					| `keypair`         | `{ privateKeyPem, privateKeyJwk }`                       |                  |
 | 
				
			||||||
 | 
					| `account`         | `{ id: "an-arbitrary-id" }`                              | account only     |
 | 
				
			||||||
 | 
					| `subscriberEmail` | `webhost@example.com`                                    | account only     |
 | 
				
			||||||
 | 
					| `certificate`     | `{ id: "an-arbitrary-id" }`                              | certificate only |
 | 
				
			||||||
 | 
					| `subject`         | `example.com`                                            | certificate only |
 | 
				
			||||||
 | 
					| `pems`            | `{ privkey, cert, chain, issuedAt, expiresAt }`          | certificate only |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Simple Example
 | 
					### Account Keypair
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					```js
 | 
				
			||||||
function approveDomains(opts) {
 | 
					accounts.setKeypair = async function({
 | 
				
			||||||
    // Allow only example.com and *.example.com (such as foo.example.com)
 | 
					    env,
 | 
				
			||||||
 | 
					    basePath,
 | 
				
			||||||
    // foo.example.com => *.example.com
 | 
					    directoryUrl,
 | 
				
			||||||
    var wild =
 | 
					    email,
 | 
				
			||||||
        "*." +
 | 
					    account
 | 
				
			||||||
        opts.domain
 | 
					}) {
 | 
				
			||||||
            .split(".")
 | 
					    var id = account.id || email;
 | 
				
			||||||
            .slice(1)
 | 
					    var serverDir = directoryUrl.replace("https://", "");
 | 
				
			||||||
            .join(".");
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
    if ("example.com" !== opts.domain && "*.example.com" !== wild) {
 | 
					
 | 
				
			||||||
        cb(new Error(opts.domain + " is not allowed"));
 | 
					```js
 | 
				
			||||||
    }
 | 
					accounts.checkKeypair = async function({
 | 
				
			||||||
 | 
					    env,
 | 
				
			||||||
    var result = {
 | 
					    basePath,
 | 
				
			||||||
        subject: "example.com",
 | 
					    directoryUrl,
 | 
				
			||||||
        altnames: ["example.com", "*.example.com"]
 | 
					    email,
 | 
				
			||||||
    };
 | 
					    account
 | 
				
			||||||
    return Promise.resolve(result);
 | 
					}) {
 | 
				
			||||||
}
 | 
					    var id = account.id || email;
 | 
				
			||||||
```
 | 
					    var serverDir = directoryUrl.replace("https://", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Realistic Example
 | 
					    return {
 | 
				
			||||||
 | 
					        privateKeyPem,
 | 
				
			||||||
```js
 | 
					        privateKeyJwk
 | 
				
			||||||
function approveDomains(opts, certs, cb) {
 | 
					    };
 | 
				
			||||||
    var related = getRelated(opts.domain);
 | 
					};
 | 
				
			||||||
    if (!related) {
 | 
					```
 | 
				
			||||||
        cb(new Error(opts.domain + " is not allowed"));
 | 
					
 | 
				
			||||||
    }
 | 
					### Certificate Keypair
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    opts.subject = related.subject;
 | 
					```js
 | 
				
			||||||
    opts.domains = related.domains;
 | 
					certificate.setKeypair = async function({
 | 
				
			||||||
 | 
					    env,
 | 
				
			||||||
    cb({ options: opts, certs: certs });
 | 
					    basePath,
 | 
				
			||||||
}
 | 
					    directoryUrl,
 | 
				
			||||||
```
 | 
					    subject,
 | 
				
			||||||
 | 
					    certificate
 | 
				
			||||||
```js
 | 
					}) {
 | 
				
			||||||
function getRelated(domain) {
 | 
					    var id = account.id || email;
 | 
				
			||||||
    var related;
 | 
					    env = env || directoryUrl.replace("https://", "");
 | 
				
			||||||
    var wild =
 | 
					};
 | 
				
			||||||
        "*." +
 | 
					```
 | 
				
			||||||
        domain
 | 
					
 | 
				
			||||||
            .split(".")
 | 
					```js
 | 
				
			||||||
            .slice(1)
 | 
					certificate.checkKeypair = async function({
 | 
				
			||||||
            .join(".");
 | 
					    env,
 | 
				
			||||||
    if (
 | 
					    basePath,
 | 
				
			||||||
        Object.keys(allAllowedDomains).some(function(k) {
 | 
					    directoryUrl,
 | 
				
			||||||
            return allAllowedDomains[k].some(function(name) {
 | 
					    subject,
 | 
				
			||||||
                if (domain === name || wild === name) {
 | 
					    certificate
 | 
				
			||||||
                    related = { subject: k, altnames: allAllowedDomains[k] };
 | 
					}) {
 | 
				
			||||||
                    return true;
 | 
					    var id = account.id || email;
 | 
				
			||||||
                }
 | 
					    env = env || directoryUrl.replace("https://", "");
 | 
				
			||||||
            });
 | 
					
 | 
				
			||||||
        })
 | 
					    return {
 | 
				
			||||||
    ) {
 | 
					        privateKeyPem,
 | 
				
			||||||
        return related;
 | 
					        privateKeyJwk
 | 
				
			||||||
    }
 | 
					    };
 | 
				
			||||||
}
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```js
 | 
					### Certificate PEMs
 | 
				
			||||||
var allAllowedDomains = {
 | 
					
 | 
				
			||||||
    "example.com": ["example.com", "*.example.com"],
 | 
					```js
 | 
				
			||||||
    "example.net": ["example.net", "*.example.net"]
 | 
					certificate.set = async function({
 | 
				
			||||||
 | 
					    env,
 | 
				
			||||||
 | 
					    basePath,
 | 
				
			||||||
 | 
					    directoryUrl,
 | 
				
			||||||
 | 
					    subject,
 | 
				
			||||||
 | 
					    certificate,
 | 
				
			||||||
 | 
					    pems
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					    var id = account.id || email;
 | 
				
			||||||
 | 
					    env = env || directoryUrl.replace("https://", "");
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					certificate.check = async function({
 | 
				
			||||||
 | 
					    env,
 | 
				
			||||||
 | 
					    basePath,
 | 
				
			||||||
 | 
					    directoryUrl,
 | 
				
			||||||
 | 
					    subject,
 | 
				
			||||||
 | 
					    certificate
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					    var id = account.id || email;
 | 
				
			||||||
 | 
					    env = env || directoryUrl.replace("https://", "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        privkey,
 | 
				
			||||||
 | 
					        cert,
 | 
				
			||||||
 | 
					        chain,
 | 
				
			||||||
 | 
					        issuedAt,
 | 
				
			||||||
 | 
					        expiresAt
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@ var mkdirpAsync = PromiseA.promisify(require("@root/mkdirp"));
 | 
				
			|||||||
// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
 | 
					// Use certificate.id, or subject, if id hasn't been set, to find a certificate.
 | 
				
			||||||
// Return an object with string PEMs for cert and chain (or null, not undefined)
 | 
					// Return an object with string PEMs for cert and chain (or null, not undefined)
 | 
				
			||||||
certificates.check = function(opts) {
 | 
					certificates.check = function(opts) {
 | 
				
			||||||
    // { certificate.id, subject, ... }
 | 
					    // { directoryUrl, subject, certificate.id, ... }
 | 
				
			||||||
    var id = (opts.certificate && opts.certificate.id) || opts.subject;
 | 
					    var id = (opts.certificate && opts.certificate.id) || opts.subject;
 | 
				
			||||||
    //console.log('certificates.check for', opts);
 | 
					    //console.log('certificates.check for', opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    "name": "greenlock-store-fs",
 | 
					    "name": "greenlock-store-fs",
 | 
				
			||||||
    "version": "3.2.1",
 | 
					    "version": "3.2.2",
 | 
				
			||||||
    "description": "A file-based certificate store for greenlock that supports wildcards.",
 | 
					    "description": "A file-based certificate store for greenlock that supports wildcards.",
 | 
				
			||||||
    "homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
 | 
					    "homepage": "https://git.rootprojects.org/root/greenlock-store-fs.js",
 | 
				
			||||||
    "main": "index.js",
 | 
					    "main": "index.js",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user