Skip to content

Instantly share code, notes, and snippets.

@AnalogGhost
Forked from lukemelia/main.js
Created June 23, 2016 11:59
Show Gist options
  • Save AnalogGhost/8a9ba61c62dbcd95e30f2e3d8d8a5eb0 to your computer and use it in GitHub Desktop.
Save AnalogGhost/8a9ba61c62dbcd95e30f2e3d8d8a5eb0 to your computer and use it in GitHub Desktop.

Revisions

  1. @lukemelia lukemelia created this gist Jun 3, 2016.
    109 changes: 109 additions & 0 deletions main.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,109 @@
    var LE = require('letsencrypt');
    var pem = require('pem');
    var RSVP = require('rsvp');
    var fs = require('fs');
    var path = require('path');
    var mkdirp = require('mkdirp');

    var domains, herokuAppName, duplicate;
    if (process.env.YAPP_ENV === 'qa') {
    domains = ['heroku.yappqa.us', 'my.yappqa.us', 'api.yappqa.us', 'support.yappqa.us' ];
    herokuAppName = 'qa-yapp-cedar';
    duplicate = true; // create new cert even if they are less than 1 week old
    } else if (process.env.YAPP_ENV === 'prod') {
    domains = ['heroku.yapp.us', 'my.yapp.us', 'api.yapp.us', 'support.yapp.us'];
    herokuAppName = 'yapp-cedar';
    duplicate = false;
    } else {
    throw new Error('Must provide valid YAPP_ENV (qa or prod)');
    }

    var redisUrlExtraction = new RSVP.Promise(function(resolve, reject){
    var exec = require('child_process').exec;
    exec('heroku config:get REDISTOGO_URL --app ' + herokuAppName, function (error, stdout, stderr) {
    var redisUrl = stdout.replace(/\n/, '').replace(/\/\/redistogo:/, '//:');
    if (error) {
    reject(error);
    } else {
    resolve(redisUrl);
    }
    });
    });

    var createPrivateKey = RSVP.denodeify(pem.createPrivateKey);

    var privateKeyGeneration = createPrivateKey(2048).then(function(privateKey) {
    var pemPath = require('homedir')() + '/letsencrypt/etc/live/' + domains[0] + '/privkey.pem';
    mkdirp.sync(path.dirname(pemPath));
    fs.writeFileSync(pemPath, privateKey.key);
    }).catch(function(reason){
    console.log(reason);
    throw reason;
    });

    privateKeyGeneration.then(function(){
    var config = {
    server: LE.productionServerUrl,
    manual: true,
    configDir: require('homedir')() + '/letsencrypt/etc',
    privkeyPath: ':config/live/:hostname/privkey.pem',
    fullchainPath: ':config/live/:hostname/fullchain.pem',
    certPath: ':config/live/:hostname/cert.pem',
    chainPath: ':config/live/:hostname/chain.pem',
    debug: true
    };

    var handlers = {
    setChallenge: function (opts, hostname, key, val, cb) {
    // called during the ACME server handshake, before validation
    redisUrlExtraction.then(function(redisUrl){
    var redis = require("redis");
    var redisClient = redis.createClient(redisUrl);
    redisClient.set("letsencrypt:" + key, val, function(err){
    // console.log("set redis key letsencrypt:" + key + " = " + val);
    if (err) {
    console.log(err);
    throw err;
    }
    cb();
    });
    }).catch(function(reason){
    console.log(reason);
    throw reason;
    });
    },
    removeChallenge: function (opts, hostname, key, cb) {} // called after validation on both success and failure
    };

    var le = LE.create(config, handlers);

    le.register({ // either renews or registers
    domains: domains,
    email: '[email protected]',
    agreeTos: true,
    duplicate: true
    }, function (err, results) {
    if (err) {
    console.error('[Error]: node-letsencrypt');
    console.error(err.stack || err);
    return;
    }

    if (!results || ('object' !== typeof results)) {
    console.error("Error: An unknown error occurred. My best guess is that we got an error that we're not used to from the ACME server and accidentally interpretted it as a success... or forgot to expose the error.");
    console.error(results);
    err = new Error("Here's a stack trace, in case it helps:");
    console.error(err.stack);
    return;
    }

    // if (handlers.closeServers) {
    // handlers.closeServers();
    // }

    console.log('\nCertificate files downloaded! Please run:');
    console.log("heroku certs:update " + results.fullchainPath + ' ' + results.privkeyPath + ' --app ' + herokuAppName);

    process.exit(0);
    });
    });
    11 changes: 11 additions & 0 deletions package.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    {
    "name": "node-ssl-script",
    "dependencies": {
    "homedir": "^0.6.0",
    "letsencrypt": "1.4.4",
    "mkdirp": "^0.5.1",
    "pem": "^1.8.3",
    "redis": "^2.6.1",
    "rsvp": "^3.2.1"
    }
    }