fog-node runs on any operating system that runs Node.js: Linux, Windows, or macOS. The fog-node installer does not install software on your system. You install three prerequisites yourself, with the method that suits your OS. Then the installer configures fog-node to use them.
This is a deliberate change from FOG 1.x. The 1.x installer did the system administration itself, so it supported only the Linux distributions that it knew. fog-node leaves the system to you, so it does not need to know your OS.
CI runs the full test suite on Linux (Node 22 and 26) and on Windows (Node 22).
| Software | Version | What fog-node uses it for |
|---|---|---|
| Node.js | 22 (LTS) or 26 | Runs fog-node |
| MongoDB | 7.x | The database |
| Redis | 7.x, or a Redis-compatible server | The session store. Login fails without it, because CSRF keeps its secret in the session |
| git | any | Gets the code (you can also download a release archive) |
MongoDB and Redis can run on the same machine as fog-node, or on another one.
- Node.js: use your distribution's package, the NodeSource repository, or
the installer from https://nodejs.org. Check the major version with
node --version. - MongoDB: use the MongoDB Community Server repository for your distribution, from https://www.mongodb.com/docs/manual/administration/install-on-linux/.
- Redis: use your distribution's
redis(orvalkey) package. Enable the service so that it starts at boot. - The README section "Persistent deployment" gives a complete example. It runs MongoDB and Redis as Podman containers, fog-node as a systemd service, and nginx in front.
- Node.js: use the Windows installer from https://nodejs.org.
- MongoDB: use the MongoDB Community Server MSI from https://www.mongodb.com/try/download/community. Select "Install MongoDB as a Service", so that it starts at boot.
- Redis: Redis has no official Windows build. Use one of these:
- Memurai, a Redis-compatible Windows service (https://www.memurai.com). CI uses its developer edition.
- Redis inside WSL 2. fog-node connects to it on
127.0.0.1:6379. - The
rediscontainer image, in Docker Desktop or Podman Desktop.
- Run the commands below in PowerShell or Command Prompt. Every npm script in fog-node works in both.
- Node.js: use the installer from https://nodejs.org, or
brew install node@22. - MongoDB:
brew tap mongodb/brew, thenbrew trust mongodb/brew(newer Homebrew refuses a formula from a tap you have not trusted), thenbrew install mongodb-community@7.0, thenbrew services start mongodb-community@7.0. - Redis:
brew install redis, thenbrew services start redis.
The docker-compose.yml in this repository starts MongoDB and Redis with
docker compose up -d (or podman compose up -d). It has no authentication.
Use it for development and testing only.
git clone https://github.com/FOGProject/fog-node.git
cd fog-node
npm ci --legacy-peer-deps
npm run setup--legacy-peer-deps is required. One old chart plugin declares a peer range
that the current chart.js does not meet.
npm run setup asks these questions:
| Question | Default | Notes |
|---|---|---|
| Database server address, port, and name (MongoDB) | localhost, 27017, fog |
It connects to check them |
| Database username and password (MongoDB) | none | Leave the username empty for a MongoDB with no authentication |
| Redis URL | redis://127.0.0.1:6379/0 |
It sends PING to check it. Put a password in the URL: redis://:password@host:6379/0 |
| Each URL that browsers use, separated by commas | this computer's name, localhost, and each of its external IPv4 addresses, on port 1337 |
See "Browser URLs" below |
| Image directory | /images on Linux, /Users/Shared/fog/images on macOS, C:\fog\images on Windows |
It creates the directory and checks that it can write there |
| Administrator email and password | none | At least 8 characters |
| Sample data | no | For trying the UI. Not for production |
The installer writes two git-ignored files, config/local.js and
config/models.js. It changes no tracked file.
Every page opens a socket.io connection. fog-node accepts that connection only
from the URLs that you give the installer. This applies in every mode, not only
in production. From any other URL, the browser console shows socket connection
errors. No page depends on the socket yet, but live task progress will (see
docs/roadmap.md, Phase 2).
For example, if you give only http://fogserver:1337, then
http://10.0.0.5:1337 gets socket errors. List every URL that people use. If a
reverse proxy is in front, list the proxy's URL, for example
https://fog.example.com.
You can run npm run setup again to change the answers. It keeps the data
encryption key in config/models.js, because a new key makes encrypted data
unreadable. It also keeps the existing Administrator account. A re-run does not
change that account's email or password, and the installer says so.
Setup makes the certificate authority (CA) files for fog-agent in the pki/
folder of the application folder. A custom.pkiDir in config/local.js moves
the folder, and a re-run keeps it. Every enrolled fog-agent pins the root
certificate pki/root.pem. Back up the pki/ folder together with the
database. The pki/ folder holds the CA keys, so only the user that runs
fog-node may read it.
Setup records the SHA-256 fingerprint of the root in the database, in the
setting FOG_AGENT_ROOT_FINGERPRINT. While that setting is set, setup stops if
pki/root.pem is missing or is a different root. The error shows the recorded
fingerprint. A reinstall that wipes the application folder causes this. Restore
the pki/ folder from your backup, then run setup again. Until you do, fog-node
does not sign agent certificates.
To start over with a new root on purpose, run
npm run setup -- --new-agent-root (npm run setup:dev -- --new-agent-root
for development). Setup renames the four CA files that exist in pki/. Each
new name has a timestamp suffix. Setup then makes new CAs. Setup records the new
fingerprint. You must then re-enroll every fog-agent by hand with the new
ca.cert.pem.
Setup also keeps a backup of the four CA files in the database: root.key,
root.pem, agent-ca.key and agent-ca.pem. A passphrase protects the
backup. The backup is encrypted with a key made from the passphrase (scrypt,
then AES-256-GCM), so a copy of the database alone does not give the CA keys.
fog-node does not keep the passphrase.
A database backup plus the passphrase restores the four CA files. Run setup
again with an empty pki/ folder on the same database. Setup sees that
pki/root.pem is missing, asks for the passphrase, writes the four files, and
makes the server certificate again. Setup restores only the agent CA that the
database records. A backup of an older agent CA would cut off the agents
enrolled since, so setup refuses it.
Setup asks for the passphrase when it makes the first backup, and again when
the CAs change (for example after --new-agent-root). The recommended answer
is a generated passphrase of 6 words. Setup prints it once. Store it in a
password manager at once. A passphrase that you type must have at least 20
characters.
The command npm run agent-ca manages the backup:
npm run agent-ca -- backupseals the CA files inpki/and replaces the backup. It prints a new generated passphrase. Use this to make the first backup of an existing install, or to change the passphrase.npm run agent-ca -- restorewrites the four CA files from the backup into an emptypki/folder, then makes the bundle and the server certificate.npm run agent-ca -- statusshows whether a backup exists, and whether it matches the recorded CAs and the files inpki/. It never shows the passphrase.
backup and restore also take --passphrase-file <path>: the first line of
that file is the passphrase. npm run setup:dev takes
--agent-ca-passphrase-file <path> for a restore.
An install without prompts reads the passphrase from pki.passphrase in the
answers file, for example "pki": {"passphrase": "crane mosaic fluid oyster banjo thrift"}.
That file then holds the passphrase, so store it as you store the passphrase,
or delete it after the install. Without pki.passphrase, setup makes no
backup and tells you to run npm run agent-ca -- backup.
If you lose the passphrase, the backup cannot be opened. Restore the pki/
folder from a file backup, or start over with --new-agent-root.
fog-node runs a second, HTTPS listener for fog-agent. It uses the port in
custom.agentTlsPort in config/local.js. The default is 8443. The agent
proves itself with its client certificate on this port (mTLS), so it works on
any OS with no proxy setup. The listener serves only the agent routes
(/agent/v1/...) and the two CA files (/management/other/ca.cert.pem and
.der). Every other path, such as the web UI, the login, and /api/v1, answers
404 on this port. An agent uses one base URL for everything:
https://<host>:<port>, for example https://fogserver:8443.
To change the port, run npm run setup again, or edit custom.agentTlsPort
and restart fog-node. The value 0 turns the listener off. The answers file
key is server.agentTlsPort. If the port is in use, fog-node logs a warning
that names the port and runs without the listener.
The listener serves pki/server.pem, which the root certificate pki/root.pem
signed. An agent pins the root, and checks the host in the URL against the names
and addresses in server.pem. Setup writes that list to custom.agentTlsSans:
localhost, this computer's name and addresses, and the host of each browser
URL. If agents use another name, add it to custom.agentTlsSans.
At each start, fog-node checks the server certificate only. It makes
pki/server.pem and pki/server.key from the existing root when they are
missing. It makes them again when the list changes, fewer than 30 days remain,
or the root no longer verifies them. It renames the old pair with a timestamp
suffix. This needs pki/root.key. Without it, fog-node logs one warning. It
then starts the listener with the existing server.pem and server.key. If
either is missing, it runs without the listener.
A start never makes a root or an agent CA. A new agent CA would cut off every
enrolled agent, so only npm run setup (or npm run setup:dev) makes one. If
pki/root.pem or pki/agent-ca.pem is missing, or the root does not verify
the agent CA, fog-node logs one warning that names npm run setup. It then
runs without the listener.
To script an install, put the answers in a JSON file and run
npm run setup -- --answers answers.json. Each key is the same question as
above, with the same default and the same check. A wrong answer or a failed
check ends the install with exit code 1. It does not ask again.
{
"database": {"host": "localhost", "port": 27017, "database": "fog", "username": "", "password": ""},
"redis": {"url": "redis://127.0.0.1:6379/0"},
"server": {"urls": "http://fogserver:1337, http://10.0.0.5:1337", "imageStorePath": "/images"},
"admin": {"email": "admin@example.com", "password": "change-me-now"},
"seed": {"seed": false}
}Leave out a key to take its default. admin.email and admin.password have
no default, so they are required. seed.seed must be true or false. The
file holds the Administrator password, so delete it after the install.
npm startnpm start runs node app.js --prod, production mode. At each start it builds
the browser assets into two minified bundles.
Then open the URL that you gave the installer, for example
http://fogserver:1337, and log in as Administrator. To use a different port, run node app.js --prod --port=8080.
For development, run node app.js. Development mode serves each asset file
separately and rebuilds them when you change one.
fog-node is one long-running Node process. Use the service manager of your OS
to start it at boot and restart it if it stops. Set its working directory to
the fog-node directory, and run node app.js --prod (what npm start runs).
- Linux: a systemd unit. The README section "Persistent deployment" has a complete example.
- Windows: a service wrapper such as NSSM (https://nssm.cc), or a Task Scheduler task that runs at startup.
- macOS: a launchd agent (a
.plistfile in~/Library/LaunchAgents).
Start fog-node after MongoDB and Redis. If fog-node starts first, it fails to connect and exits, so set the service to restart on failure.
Run these steps in the fog-node directory, in this order:
- Stop fog-node: stop the service, or end the
nodeprocess. git pullnpm ci --legacy-peer-depsnpm run migrate- Start fog-node.
Stop fog-node first. A new version can store a record in a new shape, and the
old code still writes the old shape until it stops. For example, schema
revision 2 renames the host field tags to groups: the old code writes
tags, and the new code reads only groups.
npm run migrate moves the database to the schema revision of the new code.
It runs only the revisions that the database does not have yet, and it says
"Migration not needed" when there are none. It asks about a database backup
before it changes anything. Make the backup, for example with mongodump.
That backup is the rollback: the migrator has no command that undoes a
revision.
fog-node listens on port 1337. To serve it on 80 and 443, put a reverse proxy
in front: nginx, Caddy, Apache, or IIS with URL Rewrite. Set the proxy to pass
WebSocket upgrades through, for the socket.io connection (see "Browser URLs").
If you do this, give the installer the proxy's URL (for example
https://fog.example.com), not :1337.
fog-node records the client address (req.ip) in the audit log and in the agent
enrollment rows. By default it records the address of the connection, which is the
proxy's address behind a reverse proxy. To record the client address, set
http: {trustProxy: true} in config/local.js, and make the proxy send
X-Forwarded-For. npm run setup keeps this setting when you run it again.