Verified Commit 0fdd9af9 authored by Aral Balkan's avatar Aral Balkan
Browse files

Cosmetic updates to the command-line interface

parents 1894d128 6b77451b
......@@ -21,9 +21,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## Changed
- (Breaking) Simplified commandline vocabulary to use command syntax (not options syntax).
- Renamed `dist` folder to `dist-iws` so we can exclude it from the source code zip (used for the binaries) without also exclusing some of the node modules that have dist directories that are required for proper functioning.
- Production use is only supported on platforms with systemd.
- (Breaking) Simplified commandline vocabulary; now using command syntax (not options syntax).
- Running as daemon is only supported on platforms with systemd.
## Fixed
......
......@@ -8,7 +8,7 @@ Indie Web Server is a secure and seamless [Small Tech](https://ar.al/2019/03/04/
- Develop with automatically-provisioned locally-trusted TLS thanks to [mkcert](https://github.com/FiloSottile/mkcert) via [Nodecert](https://source.ind.ie/hypha/tools/nodecert).
- Test and deploy with automatically-provisioned globally-trusted TLS thanks to [Let’s Encrypt](https://letsencrypt.org/) via [ACME TLS](https://source.ind.ie/hypha/tools/acme-tls) (with an A score on [SSL Labs SSL Server Test](https://www.ssllabs.com/ssltest)) and the seamlessly-integrated [pm2](https://pm2.io/runtime/) process manager.
- Test and deploy with automatically-provisioned globally-trusted TLS thanks to [Let’s Encrypt](https://letsencrypt.org/) via [ACME TLS](https://source.ind.ie/hypha/tools/acme-tls) (with an A score on [SSL Labs SSL Server Test](https://www.ssllabs.com/ssltest)) and integrated systemd support.
## Install
......@@ -99,6 +99,14 @@ npm test
web-server test/site
```
__Note:__ for commands that require root privileges (i.e., `enable` and `disable`), Indie Web Server will automatically restart itself using sudo and Node must be available for the root account. If you’re using [nvm](https://github.com/creationix/nvm), you can enable this via:
```shell
# Replace v10.15.3 with the version of node you want to make available globally.
sudo ln -s "$NVM_DIR/versions/node/v10.15.3/bin/node" "/usr/local/bin/node"
sudo ln -s "$NVM_DIR/versions/node/v10.15.3/bin/npm" "/usr/local/bin/npm"
```
### Native binaries
```shell
......
......@@ -115,13 +115,38 @@ switch (true) {
// Logs (proxy: journalctl --follow --unit web-server)
case command.isLogs:
ensureJournalctl()
console.log(`\n 📜 Tailing logs (press Ctrl+C to exit).\n`)
childProcess.spawn('journalctl', ['--follow', '--unit', 'web-server'], {env: process.env, stdio: 'inherit'})
break
// Status (proxy: systemctl status web-server)
case command.isStatus:
ensureSystemctl()
childProcess.spawn('systemctl', ['status', 'web-server'], {env: process.env, stdio: 'inherit'})
let isActive
try {
childProcess.execSync('systemctl is-active web-server', {env: process.env, stdio: 'pipe'})
isActive = true
} catch (error) {
isActive = false
}
let isEnabled
try {
childProcess.execSync('systemctl is-enabled web-server', {env: process.env, stdio: 'pipe'})
isEnabled = true
} catch (error) {
isEnabled = false
}
const activeState = isActive ? clr('active', 'green') : clr('inactive', 'red')
const enabledState = isEnabled ? clr('enabled', 'green') : clr('disabled', 'red')
const stateEmoji = (isActive && isEnabled) ? '' : ''
console.log(`\n ${stateEmoji} Indie Web Server is ${activeState} and ${enabledState}.\n`)
break
// Off (turn off the server daemon and remove it from startup items).
......@@ -129,8 +154,9 @@ switch (true) {
ensureRoot('disable')
ensureSystemctl()
try {
childProcess.execSync('sudo systemctl disable web-server', {env: process.env})
childProcess.execSync('sudo systemctl stop web-server', {env: process.env})
childProcess.execSync('sudo systemctl disable web-server', {env: process.env, stdio: 'pipe'})
childProcess.execSync('sudo systemctl stop web-server', {env: process.env, stdio: 'pipe'})
console.log('\n 🎈 Server stopped and removed from startup.\n')
} catch (error) {
console.error(error, '\n 👿 Error: Could not disable web server.\n')
process.exit(1)
......@@ -203,7 +229,7 @@ switch (true) {
let accountName
try {
// Courtesy: https://www.unix.com/302402784-post4.html
accountName = childProcess.execSync(`awk -v val=${accountUID} -F ":" '$3==val{print $1}' /etc/passwd`).toString()
accountName = childProcess.execSync(`awk -v val=${accountUID} -F ":" '$3==val{print $1}' /etc/passwd`, {env: process.env, stdio: 'pipe'}).toString()
} catch (error) {
console.error(error, '\n 👿 Error: could not get account name.\n')
process.exit(1)
......@@ -232,15 +258,17 @@ switch (true) {
// Save the systemd service unit.
fs.writeFileSync('/etc/systemd/system/web-server.service', unit, 'utf-8')
// Enable and start the systemd service.
//
// Enable and start systemd service.
//
try {
// Start.
childProcess.execSync('sudo systemctl start web-server', {env: process.env, stdio: 'pipe'})
console.log(`${webServer.version()}\n 😈 Launched as daemon on ${clr(`https://${os.hostname()}`, 'green')} serving ${clr(pathToServe, 'cyan')}\n`)
// Enable.
childProcess.execSync('sudo systemctl enable web-server', {env: process.env})
childProcess.execSync('sudo systemctl enable web-server', {env: process.env, stdio: 'pipe'})
console.log(` 😈 Installed for auto-launch at startup.\n`)
// Start.
childProcess.execSync('sudo systemctl start web-server', {env: process.env})
console.log(`${webServer.version()}\n 😈 Launched as daemon on https://${os.hostname()} serving ${pathToServe}\n`)
} catch (error) {
console.error(error, `\n 👿 Error: could not enable web server.\n`)
process.exit(1)
......
......@@ -5,6 +5,8 @@ const path = require('path')
const os = require('os')
const childProcess = require('child_process')
const ansi = require('ansi-escape-sequences')
const express = require('express')
const helmet = require('helmet')
const morgan = require('morgan')
......@@ -29,7 +31,7 @@ class WebServer {
// the version set in the package.json file. (Synchronous.)
version () {
const version = JSON.parse(fs.readFileSync(path.join(__dirname, './package.json'), 'utf-8')).version
return `\n 💖 Indie Web Server v${version} running on Node ${process.version}\n`
return `\n 💖 Indie Web Server v${version} ${clr(`(running on Node ${process.version})`, 'italic')}\n`
}
// Returns an https server instance – the same as you’d get with
......@@ -78,7 +80,7 @@ class WebServer {
portSuffix = `:${serverPort}`
}
const location = global ? os.hostname() : `localhost${portSuffix}`
console.log(`\n 🎉 Serving ${pathToServe} on https://${location}\n`)
console.log(`\n 🎉 Serving ${clr(pathToServe, 'cyan')} on ${clr(`https://${location}`, 'green')}\n`)
}
// Check if a 4042302 (404 → 302) redirect has been requested.
......@@ -91,10 +93,10 @@ class WebServer {
const _4042302Path = path.join(pathToServe, '4042302')
// TODO: We should really be checking that this is a file, not that it
// ===== exists, on the off-chance that somone might have a directory
// ===== exists, on the off-chance that someone might have a directory
// with that name in their web root (that someone was me when I
// erroneously ran web-server on the directory that I had the
// actualy 4042302 project folder in).
// actually 4042302 project folder in).
const has4042302 = fs.existsSync(_4042302Path)
let _4042302 = null
if (has4042302) {
......@@ -315,3 +317,13 @@ class WebServer {
}
module.exports = new WebServer()
//
// Helpers.
//
// Format ansi strings.
// Courtesy Bankai (https://github.com/choojs/bankai/blob/master/bin.js#L142)
function clr (text, color) {
return process.stdout.isTTY ? ansi.format(text, color) : text
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment