Files
vim-ale/node
AJ ONeal 84c943b160 feat(node): merge official + unofficial builds into single cache
Add unofficial_url to node/releases.conf and update the nodedist
fetcher/classifier to fetch from both URLs. Raw entries are stored
with "official/" or "unofficial/" tag prefixes so they don't overwrite
each other. The classifier picks the correct base URL from the prefix.

This matches the Node.js releases.js behavior which merges both sources,
adding musl, riscv64, loong64, and 7z builds from unofficial.
2026-03-10 12:35:18 -06:00
..
2026-03-08 19:38:49 -06:00

title, homepage, tagline
title homepage tagline
Node.js https://nodejs.org Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

To update or switch versions, run webi node@<tag>.
(you can use @lts for long-term support, @beta for pre-releases, or @x.y.z for a specific version)

Files

These are the files / directories that are created and/or modified with this install:

~/.config/envman/PATH.env
~/.local/opt/node/
~/.node/
~/.node_repl_history
~/.npm/
~/.npmrc

Cheat Sheet

Node is great for simple, snappy HTTP(S) servers, and for stitching APIs together with minimal fuss or muss.

Installing node via webi will:

  • pick a compatible version from the Node Releases API
  • download and unpack to $HOME/.local/opt/node/
  • update your PATH in $HOME/.config/envman/PATH.env
  • absolutely leave system file permissions alone
    • (no dreaded sudo npm permission errors)

Hello World

node -e 'console.log("Hello, World!")'
> Hello, World!

How to Lint and Fmt Node Code

Just by installing these alone, most code editors (vim, VS Code, etc) can automatically use them for JavaScript:

npm install --location=global fixjson@1 jshint@2 prettier@3

To run them manually on your code;

  • prettier (fmt)
    touch .prettierrc.json .prettierignore
    prettier -w '**/*.{md,js,jsx,html}'
    
  • jshintrc (lint)
    touch .jshintrc .jshintignore
    jshint -c ./.jshintrc *.js */*.js
    
  • fixjson
    (turns JavaScript Objects with comments, trailing commas, etc into actual json)
    fixjson -i 2 -w ./package.json
    

To run with GitHub Actions on PRs see "Fmt & Lint Automatically" below.

A Simple Web Server

server.js:

var http = require('http');
var app = function (req, res) {
  res.end('Hello, World!');
};
http.createServer(app).listen(8080, function () {
  console.info('Listening on', this.address());
});
node server.js

Generate a Secure Random Key

This generates a hex-encoded 128-bit random key.

node -p 'crypto.randomBytes(16).toString("hex")'

This generates a url-safe base64 256-bit random key.

node -p 'crypto.randomBytes(32).toString("base64")
            .replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "")'

An Express App

mkdir my-server
pushd my-server/
npm init
npm install --save express

app.js:

'use strict';

var express = require('express');
var app = express();

app.use('/', function (req, res, next) {
  res.end('Hello, World!');
});

module.exports = app;

server.js:

'use strict';

var http = require('http');
var app = require('./app.js');

http.createServer(app).listen(8080, function () {
  console.info('Listening on', this.address());
});
npm start

How to Reverse Proxy to Node

You can use caddy:

./Caddyfile:

localhost {
    # Reverse Proxy to your Node app's API
    handle /api/* {
        reverse_proxy localhost:3000
    }

    # Handle static files directly with Caddy
    handle /* {
        root * ./public/
        file_server
    }
}
caddy run --config ./Caddyfile

See the Caddy Cheat Sheet for more info, such as how to use X-SendFile to .

How to Allow Node to bind on 80 & 443

You can... but should you?

Are You Sure?

Typically you should use caddy as a Reverse Proxy (see above).

Yes

On macOS all programs have permissions to use privileged ports by default.

On Linux there are several ways to add network capabilities for privileged ports:

  1. Use setcap-netbind

    webi setcap-netbind
    setcap-netbind caddy
    
  2. Use setcap directly

    my_caddy_path="$( command -v caddy )"
    my_caddy_absolute="$( readlink -f "${my_caddy_path}" )"
    
    sudo setcap cap_net_bind_service=+ep "${my_caddy_absolute}"
    
  3. Add the --set-cap-net-bind option to serviceman (see below)

  4. Update the systemd config directly:

    CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
    

How to run a Node app as a User Service

Also called "Login Item", "Startup Item" or "User Unit", this is how you run a Node app as a Non-System (Unprivileged) Service on Mac, Windows, and Linux:

  1. Install serviceman

    webi serviceman
    
  2. Use Serviceman to create a Launch Agent (macOS), Startup Item (Windows), or User Unit (Linux):

    my_username="$(id -u -n)"
    
    serviceman add --agent --name my-node-project -- \
        caddy run --config ./Caddyfile --envfile ~/.config/caddy/env
    
  3. Manage the service

    • On macOS

      # Manage (-w to disable/enable on login)
      launchctl unload -w ~/Library/LaunchAgents/my-node-project.plist
      launchctl load -w ~/Library/LaunchAgents/my-node-project.plist
      
      # View Logs
      tail -f ~/.local/share/my-node-project/var/log/my-node-project.log
      
    • On Windows

      # Manage
      serviceman stop caddy
      serviceman start caddy
      
      # View Logs
      type ~/.local/share/my-node-project/var/log/my-node-project.log | more
      
    • On Linux

      # Manage
      systemctl --user disable my-node-project
      systemctl --user stop my-node-project
      systemctl --user enable my-node-project
      systemctl --user start my-node-project
      
      # View Logs
      journalctl --user -xef -u my-node-project
      

How to run a Node app as a System Service

pushd ./my-node-project/

serviceman add --name 'my-node-project' -- \
    npm run start

... with auto-reload in Dev

pushd ./my-node-project/

serviceman add --name 'my-node-project' -- \
    npx -p nodemon@3 -- nodemon ./server.js

View Logs & Restart

sudo journalctl -xef -u my-node-project
sudo systemctl restart my-node-project

How to Fmt & Lint Automatically

Here are some useful scripts to have in your package.json, and a sample file to run them with GitHub Actions (Workflows):

npm run
        fmt
        lint
        bump <major|minor|patch|prerelease>
        prepublish # also runs after npm install
# bump
npm pkg set scripts.bump='npm version -m "chore(release): bump to v%s"'

# fmt
npm pkg set scripts.fmt='npm run fixjson && npm run prettier'
npm pkg set scripts.prettier="npx -p prettier@2 -- prettier --write '**/*.{md,js,jsx,json,css,html,vue}'"
npm pkg set scripts.fixjson="npx -p fixjson@1 -- fixjson -i 2 -w '*.json' '*/*.json'"
echo 'node_modules' >> .prettierignore

# lint
npm pkg set scripts.lint='npm run jshint'
npm pkg set scripts.jshint="npx -p jshint@2 -- jshint -c ./.jshintrc ./*.js ./*/*.json"
echo 'node_modules' >> .jshintignore

# prepublish
npm pkg set scripts.prepublish='npm run lint && npm run fmt'

To run these automatically for all PRs on GitHub:

.github/workflows/node.js.yml:

name: Node.js CI
on:
  push:
    branches: ['main']
  pull_request:
jobs:
  build:
    name: "Fmt, Lint, & Test"
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version:
          - 20.x
          - latest
    steps:
      - uses: actions/checkout@v3
      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}
      - name: "Webi: Install 'shfmt' and 'shellcheck', and update PATH"
        run: |
          #sh ./_scripts/install-ci-deps
          echo "${HOME}/.local/bin" >> $GITHUB_PATH
      - run: node --version
      - run: npm run fmt
      - run: npm clean-install
      - run: npm run lint
      - run: npm run test

How to Install Node's Linux Dependencies

Typically Node just needs openssl and libstdc++.

# Apline
sudo apk add --no-cache libstdc++ libssl3
# Debian / Ubuntu
sudo apt-get install -y libstdc++6 libssl3