How to Install Deno on RHEL 7
Deno is a modern, secure runtime for JavaScript and TypeScript built on V8 and Rust. Created by Ryan Dahl — the original author of Node.js — Deno was designed to address architectural decisions in Node.js that became pain points over time: no built-in TypeScript support, a complex and mutable node_modules directory, implicit file system and network access, and a non-standard module system. Deno ships as a single executable with TypeScript compilation, a built-in formatter, linter, test runner, and bundler baked in. Its security-first permissions model requires you to explicitly grant access to the file system, network, and environment variables, making it far safer to run untrusted scripts. This tutorial covers installing Deno on RHEL 7, understanding its permissions model, running TypeScript files, and using the Deno task runner and compiler.
Prerequisites
- RHEL 7 system with a user account (Deno installs per-user, not system-wide by default).
curlorwgetavailable:sudo yum install -y curl.- Internet access to download the Deno binary from GitHub Releases.
- Approximately 100 MB of free disk space.
- Optionally,
unzipfor manual installation:sudo yum install -y unzip.
Step 1: Install Deno Using the Official Install Script
The simplest installation method is the official shell script, which detects your platform, downloads the correct binary from GitHub Releases, and places it in ~/.deno/bin/:
curl -fsSL https://deno.land/x/install/install.sh | sh
The flags used: -f silently fails on HTTP errors, -s suppresses the progress bar, -S shows errors if the download fails, and -L follows redirects. You will see output confirming the download and installation path:
######################################################################## 100.0%
Archive: /tmp/deno.zip
inflating: /root/.deno/bin/deno
Deno was installed successfully to /root/.deno/bin/deno
If the install script is blocked in your environment, you can download the binary manually from GitHub Releases:
DENO_VERSION=$(curl -sI https://github.com/denoland/deno/releases/latest |
grep -i location | sed 's/.*tag/v//' | tr -d 'rn')
curl -Lo /tmp/deno.zip
"https://github.com/denoland/deno/releases/download/v${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip"
mkdir -p ~/.deno/bin
unzip -o /tmp/deno.zip -d ~/.deno/bin
chmod +x ~/.deno/bin/deno
Step 2: Add Deno to Your PATH
The install script prints instructions to add Deno to your shell PATH. Add the following to ~/.bashrc to make deno available in all future sessions:
echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.bashrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
Verify the installation:
deno --version
deno 1.44.1 (release, x86_64-unknown-linux-gnu)
v8 12.6.228.3
typescript 5.4.5
Notice that the version output shows not only Deno itself but also the embedded V8 JavaScript engine version and the TypeScript compiler version — both are bundled inside the single deno binary.
Step 3: Run Your First TypeScript File
Create a simple TypeScript file:
cat > ~/hello.ts <<'EOF'
const greeting: string = "Hello from Deno on RHEL 7!";
const year: number = new Date().getFullYear();
console.log(`${greeting} The year is ${year}.`);
EOF
Run it with deno run:
deno run ~/hello.ts
Hello from Deno on RHEL 7! The year is 2024.
Deno compiles and runs TypeScript natively — no separate tsc compiler or ts-node package is required. The first run may take a moment as Deno caches compiled modules; subsequent runs are faster.
Step 4: Understanding Deno’s Permissions Model
One of Deno’s most important features is its security-by-default permissions model. Unlike Node.js, a Deno script cannot access the file system, make network requests, read environment variables, or execute subprocesses unless you explicitly grant permission via command-line flags.
Try running a script that fetches a URL without granting network permission:
cat > ~/fetch_demo.ts <<'EOF'
const response = await fetch("https://httpbin.org/get");
const data = await response.json();
console.log("IP:", data.origin);
EOF
deno run ~/fetch_demo.ts
error: Uncaught PermissionDenied: Requires net access to "httpbin.org", run again with the --allow-net flag
Grant network access with --allow-net:
deno run --allow-net ~/fetch_demo.ts
You can scope permissions to specific hosts:
deno run --allow-net=httpbin.org ~/fetch_demo.ts
Common Permission Flags
--allow-net— allow all network access;--allow-net=example.comrestricts to specific host--allow-read— allow file system reads;--allow-read=/tmprestricts to a directory--allow-write— allow file system writes--allow-env— allow access to environment variables--allow-run— allow spawning subprocesses--allow-ffi— allow loading dynamic libraries via FFI--allow-allor-A— grant all permissions (use carefully, equivalent to disabling the safety model)
Step 5: Using deno task
Deno has a built-in task runner configured through deno.json (Deno’s project configuration file). This replaces the scripts section of package.json in Node.js projects.
Create a project directory with a deno.json:
mkdir ~/denoapp && cd ~/denoapp
cat > deno.json <<'EOF'
{
"tasks": {
"start": "deno run --allow-net --allow-read main.ts",
"dev": "deno run --watch --allow-net --allow-read main.ts",
"fmt": "deno fmt",
"lint": "deno lint",
"test": "deno test --allow-net"
}
}
EOF
Create a simple main.ts:
cat > main.ts <<'EOF'
import { serve } from "https://deno.land/[email protected]/http/server.ts";
const handler = (req: Request): Response => {
return new Response(`Hello from Deno! Path: ${new URL(req.url).pathname}`, {
status: 200,
headers: { "content-type": "text/plain" },
});
};
console.log("Listening on http://localhost:8000");
await serve(handler, { port: 8000 });
EOF
Run the task:
deno task start
The --watch flag in the dev task causes Deno to automatically restart when source files change — ideal for development.
Step 6: Compile to a Standalone Executable with deno compile
Deno can package a script and the Deno runtime into a single self-contained executable binary — useful for distributing CLI tools:
deno compile --allow-net --output /usr/local/bin/myserver main.ts
The resulting binary has no runtime dependency on Deno being installed:
/usr/local/bin/myserver
Listening on http://localhost:8000
For cross-compilation to different targets (e.g., compiling on RHEL 7 for macOS):
deno compile --target x86_64-apple-darwin --allow-net --output myserver-macos main.ts
Step 7: Deno vs Node.js — Key Differences
- TypeScript support: Deno runs
.tsfiles natively; Node.js requirestscor ts-node. - Module system: Deno uses ES modules with URL imports (
import { serve } from "https://..."); Node.js uses CommonJS (require()) by default, with ESM support added later. - No node_modules: Deno caches modules globally in
~/.cache/deno; there is no per-projectnode_modulesdirectory. - Security: Deno denies all I/O by default; Node.js grants full access implicitly.
- Built-in tools: Deno ships with a formatter (
deno fmt), linter (deno lint), test runner (deno test), bundler (deno bundle), and doc generator (deno doc) — no external tooling required. - npm compatibility: Deno 1.28+ supports
npm:specifiers, allowing many npm packages to be used:import express from "npm:express".
Step 8: Updating Deno
Deno has a built-in self-update command:
deno upgrade
To upgrade to a specific version:
deno upgrade --version 1.44.0
To switch to the canary (nightly) channel:
deno upgrade --canary
Deno is now fully installed and operational on your RHEL 7 system. Its single-binary distribution, built-in TypeScript support, and security-first permissions model make it an attractive runtime for scripts, API servers, and CLI tools that benefit from compile-time safety and controlled resource access. The absence of a node_modules directory and the built-in toolchain (formatter, linter, test runner, compiler) reduce project setup friction significantly compared to equivalent Node.js workflows. As Deno’s npm compatibility layer continues to mature, it becomes increasingly viable as a drop-in successor for many Node.js use cases while offering a substantially improved security posture.