Node.js Runtime
Host Node.js applications on Witchly.host. Deploy from Git, install npm packages, and run any index.js-style entrypoint with dedicated resources.
languages (12 articles)
On This Page
Node.js Runtime
The Node.js egg runs Node.js 25.x via the ghcr.io/ptero-eggs/yolks:nodejs_25 image. Clone a Git repo on install, install dependencies, run any JavaScript or TypeScript-compiled-to-JS entrypoint.
Quick deploy
- dash.witchly.host → Deploy → Languages → Node.js.
- On the Startup tab, set:
Git Repo Address— e.g.https://github.com/you/your-bot.gitMain file— the entrypoint path (defaultindex.js)Additional Node packages— space-separated npm package names (optional, installed on startup)
- Start from the Console tab.
Startup flow
The egg runs this on each start:
# Pull latest if AUTO_UPDATE=1
if [[ -d .git ]] && [[ {{AUTO_UPDATE}} == "1" ]]; then git pull; fi
# Install any extra packages
if [[ ! -z ${NODE_PACKAGES} ]]; then /usr/local/bin/npm install ${NODE_PACKAGES}; fi
# Run your entrypoint
/usr/local/bin/node ${MAIN_FILE} ${NODE_ARGS}
Variables reference
| Variable | Purpose |
|---|---|
GIT_ADDRESS | Git repo URL. Leave blank to upload manually. |
BRANCH | Git branch/tag. Blank → repo default (usually main). |
USER_UPLOAD | 1 to skip auto-clone; you upload via SFTP instead. |
AUTO_UPDATE | 1 to git pull on every start. |
MAIN_FILE | Entrypoint (default index.js). |
NODE_PACKAGES | Extra npm packages to install on each boot. |
UNNODE_PACKAGES | Packages to uninstall on each boot (useful during testing). |
NODE_ARGS | Flags passed to Node (e.g., --max-old-space-size=512). |
USERNAME, ACCESS_TOKEN | For cloning private repos via HTTPS. |
Private repos
Create a GitHub/GitLab personal access token with read-only repo scope, then fill:
USERNAME— your Git usernameACCESS_TOKEN— the token
The egg clones with https://USERNAME:ACCESS_TOKEN@host/path.git under the hood.
Environment variables (your app’s)
Any process.env.* variable your app needs can be set on the Startup tab by adding custom variables — edit via the Pterodactyl Variables area, or just use a .env file in your repo and load it with dotenv:
import "dotenv/config"
console.log(process.env.DISCORD_TOKEN)
Installing dependencies
The egg automatically runs npm install on install (one time) and re-runs it if NODE_PACKAGES is set. To install packages manually:
- On the Console tab, type:
npm install <package> - Or via the Files tab, edit
package.jsonand restart — dependencies install on boot.
TypeScript
Two options:
Option A — build before deploy. Compile locally (tsc) and commit dist/ to your repo. Set MAIN_FILE=dist/index.js.
Option B — run TS directly. Add tsx or ts-node as a dependency, then override the startup to npx tsx src/index.ts. (Requires editing the startup command — ask support if the default egg constrains this.)
Logs & the console
console.log and console.error stream to the Pterodactyl console in real time. The console is also a stdin — you can type into your app if it reads from process.stdin.
Memory tuning
Node’s default heap is ~512 MB regardless of your server’s RAM. On plans with >1 GB RAM, increase it:
NODE_ARGS = --max-old-space-size=1536
(1.5 GB = 1536 MB; adjust for your plan.)
Troubleshooting
- “Cannot find module ‘foo’” — add
footopackage.jsonand restart, or setNODE_PACKAGES=foo. - Crashes with no output — check memory; if node exits with
FATAL ERROR: Ineffective mark-compacts..., raise--max-old-space-sizeor upgrade. - Git clone fails — private repo needs
USERNAME+ACCESS_TOKEN, or the.gitURL is wrong.
Next steps
- Build a Discord bot and hook it up to Redis for caching
- Use PM2-style auto-reload with nodemon during development