From 2ffc76e2423fb813c5ff624ee27541cd06437113 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 5 May 2018 19:56:28 +0000 Subject: [PATCH] add virtual hosting example --- examples/vhost.js | 95 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 examples/vhost.js diff --git a/examples/vhost.js b/examples/vhost.js new file mode 100644 index 0000000..72c830a --- /dev/null +++ b/examples/vhost.js @@ -0,0 +1,95 @@ +#!/usr/bin/env node +'use strict'; + +// This is an example for virtual hosting + +var email = 'john@example.com'; +// The prefix where sites go by name. +// For example: whatever.com may live in /srv/www/whatever.com, thus /srv/www is our path +var srv = '/srv/www/'; + + +var fs = require('fs'); +var finalhandler = require('finalhandler'); +var serveStatic = require('serve-static'); +var path = require('path'); +var hostnameRe = /^[a-z0-9][\.a-z0-9\-]+$/; + +//require('greenlock-express') +require('../').create({ + + // Let's Encrypt v2 is ACME draft 11 + version: 'draft-11' + + // You MUST change 'acme-staging-v02' to 'acme-v02' in production +, server: 'https://acme-v02.api.letsencrypt.org/directory' // staging + +, approveDomains: function (opts, certs, cb) { + // In this example the filesystem is our "database". + // We check in /srv/www for whateve.com and if it exists, it's allowed + + + // The domains being approved for the first time are listed in opts.domains + + // Certs being renewed are listed in certs.altnames + if (certs) { + opts.domains = certs.altnames; + cb(null, { options: opts, certs: certs }); + return; + } + + // TODO could test for www/no-www both in directory and IP + var e; + var hostdir = path.join(srv, opts.domains[0]); + if (!hosnameRe.test(opts.domains[0])) { + e = new Error("rejecting '" + opts.domains[0] + "' because it is not a valid domain name"); + cb(e); + return; + } + fs.readdir(hostdir, function (err, nodes) { + e = new Error("rejecting '" + opts.domains[0] + "' because '" + hostdir + "' could not be read"); + if (err || !nodes) { + console.error(err); + console.error(e); + cb(e); + return; + } + + // TODO check for some sort of htaccess.json and use email in that + // NOTE: you can also change other options such as `challengeType` and `challenge` + // opts.challengeType = 'http-01'; + // opts.challenge = require('le-challenge-fs').create({}); + opts.email = email; + opts.agreeTos = true; + cb(null, { options: opts, certs: certs }); + }); + + } + + // You MUST have access to write to directory where certs are saved + // ex: /home/foouser/acme/etc +, configDir: require('path').join(require('os').homedir(), 'acme', 'etc') + +, app: function (req, res) { + console.log(req.headers.host); + var hostname = (req.headers.host||'').toLowerCase().split(':')[0]; + // sanatize hostname to prevent unauthorized fs access + if (!hostnameRe.test(hostname)) { + res.statusCode = 404; + res.end('Bad Hostname'); + return; + } + + var serve = serveStatic(path.join(srv, hostname), { redirect: true }); + serve(req, res, finalhandler(req, res)); + } +/* + require('express')().use('/', function (req, res) { + res.setHeader('Content-Type', 'text/html; charset=utf-8') + res.end('Hello, World!\n\nšŸ’š šŸ”’.js'); + }) +*/ + +//, debug: true + +}).listen(80, 443); \ No newline at end of file