Skip to content

Instantly share code, notes, and snippets.

@ArtemGr
Last active October 4, 2021 08:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ArtemGr/7fc754b24972b28dd34de2e872a04b9f to your computer and use it in GitHub Desktop.
Save ArtemGr/7fc754b24972b28dd34de2e872a04b9f to your computer and use it in GitHub Desktop.
certbot
//@ts-check
// TODO: A function to run the `certbot`; arguments: domain, email
const fs = require ('fs');
const http = require ('http');
const os = require ('os');
/**
* Example invoking certbot for this function, on Debian 10 Buster:
*
* sudo apt install certbot
* mkdir -p ~/.certbot
* EMAIL=...
* DOMAIN=...
* certbot certonly --webroot --config-dir ~/.certbot --logs-dir ~/.certbot --work-dir ~/.certbot -n --agree-tos --email $EMAIL --domains $DOMAIN -w ~/.certbot
*
* Let's Encrypt will then look at “http://$DOMAIN/.well-known/acme-challenge/H”
* where “H” is a temporary file located at “~/.certbot/.well-known/acme-challenge/H”
*
* This function here will detect and serve the “/.well-known/acme-challenge/” requests.
* Example using it:
*
* const http = require ('http');
* const server = http.createServer ((req, res) => {
* if (certbot (req, res)) return})
* // sudo sysctl net.ipv4.ip_unprivileged_port_start=80
* server.listen (80, '0.0.0.0')
*
* Upon a successful verification certbot will print
*
* - Congratulations! Your certificate and chain have been saved at:
* /home/$USER/.certbot/live/$DOMAIN/fullchain.pem
* Your key file has been saved at:
* /home/$USER/.certbot/live/$DOMAIN/privkey.pem
* Your cert will expire on $
*
* Example of a TLS server using the files thus obtained:
*
* const tlsₒ = {
* allowHTTP1: true,
* key: fs.readFileSync (os.homedir() + '/.certbot/live/$DOMAIN/privkey.pem'),
* cert: fs.readFileSync (os.homedir() + '/.certbot/live/$DOMAIN/fullchain.pem')}
* const tlsˢ = require ('http2') .createSecureServer (tlsₒ, (req, res) => {res.writeHead (200); res.end ("hello world\n")})
* // sudo sysctl net.ipv4.ip_unprivileged_port_start=80
* tlsˢ.listen (443)
*
* @param {http.IncomingMessage} req
* @param {http.ServerResponse} res
* @returns boolean True if an ACME challenge was served
*/
exports.certbot = function (req, res) {
if (req.method != 'GET') return false
const ca = new RegExp ('^/\\.well-known/acme-challenge/([\\w-]+)$') .exec (req.url)
if (ca && ca[1].length > 31) {
const h = ca[1]
const home = os.homedir()
const path = home + '/.certbot/.well-known/acme-challenge/' + h
let payload
try {
payload = fs.readFileSync (path, {encoding: 'utf8'})
} catch (err) {
if (err.code == 'ENOENT') {
res.statusCode = 404
res.end()
return true
} else {throw err}}
res.statusCode = 200
res.setHeader ('Content-Type', 'application/octet-stream')
res.end (payload)
return true}
return false}
exports.test = function() {}
{
"name": "certbot",
"version": "1.0.0",
"description": "helps with obtaining a TLS certificate using certbot and nodejs",
"main": "certbot.js",
"scripts": {
"test": "node -e \"require('./certbot.js').test()\""
},
"contributors": [
"Artemciy"
],
"repository": {
"type": "git",
"url": "https://gist.github.com/7fc754b24972b28dd34de2e872a04b9f.git"
},
"license": "MIT",
"dependencies": {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment