Deno is a modern runtime for JavaScript and TypeScript built by Ryan Dahl, the original creator of Node.js. It addresses several design decisions in Node that aged poorly – dependency management, security defaults, and TypeScript support. Deno runs TypeScript natively without a build step, enforces a permissions-based security model, and ships as a single binary with built-in tooling. This guide covers installing Deno on RHEL 10 and Ubuntu 24.04, running your first TypeScript program, and understanding how it compares to Node.js.

What Is Deno

Deno is a JavaScript/TypeScript runtime built on V8 (the same engine Chrome and Node.js use) with Rust providing the system-level bindings. Key differences from Node.js include:

  • TypeScript first: Runs .ts files directly without tsc or a bundler
  • Secure by default: No file, network, or environment access unless explicitly granted
  • No node_modules: Dependencies are URLs, cached globally
  • Built-in tooling: Formatter, linter, test runner, and bundler included
  • Web standard APIs: Uses fetch(), Web Streams, and other browser APIs instead of Node-specific ones
  • Node compatibility: Recent versions include a Node.js compatibility layer for importing npm packages

Install Deno on RHEL 10

Deno distributes as a single binary, making installation straightforward on any Linux distribution. The official install script downloads the latest release:

curl -fsSL https://deno.land/install.sh | sh

This installs Deno to ~/.deno/bin/deno. Add it to your PATH by appending to your shell profile:

echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.bashrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Verify the installation:

deno --version

You should see output showing the Deno version, V8 version, and TypeScript version bundled with the runtime.

Alternatively, if you prefer package manager installation on RHEL 10, you can use snap:

sudo dnf install -y snapd
sudo systemctl enable --now snapd.socket
sudo snap install deno

Install Deno on Ubuntu 24.04

The same install script works on Ubuntu:

curl -fsSL https://deno.land/install.sh | sh

Add to PATH (for bash):

echo 'export DENO_INSTALL="$HOME/.deno"' >> ~/.bashrc
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Or install via snap on Ubuntu (snapd is pre-installed):

sudo snap install deno

Verify the installation:

deno --version

Run TypeScript Directly

One of Deno’s strongest features is running TypeScript without any compilation step. Create a file called hello.ts:

interface ServerInfo {
  hostname: string;
  port: number;
  uptime: string;
}

const info: ServerInfo = {
  hostname: Deno.hostname(),
  port: 8080,
  uptime: "3 days",
};

console.log(`Server: ${info.hostname}`);
console.log(`Port: ${info.port}`);
console.log(`Uptime: ${info.uptime}`);

Run it:

deno run --allow-sys hello.ts

Notice the --allow-sys flag – Deno requires it because Deno.hostname() accesses system information. Without the flag, the program fails with a permission error. This is the security model in action.

Understanding the Permissions Model

Deno runs with no permissions by default. Your code must be explicitly granted access to system resources. The key permission flags are:

  • --allow-read – Read files from disk (optionally restricted to specific paths)
  • --allow-write – Write files to disk
  • --allow-net – Make network requests (optionally restricted to specific domains/ports)
  • --allow-env – Access environment variables
  • --allow-run – Execute subprocesses
  • --allow-sys – Access system information (hostname, OS, memory)
  • --allow-all or -A – Grant all permissions (use only in development)

Permissions can be scoped. For example, allow network access only to a specific API:

deno run --allow-net=api.example.com app.ts

Or allow file reads only from a specific directory:

deno run --allow-read=/etc/myapp app.ts

This model prevents supply-chain attacks where a compromised dependency tries to read your SSH keys or phone home to a remote server.

Configure Projects with deno.json

For projects beyond a single script, create a deno.json configuration file in the project root:

{
  "tasks": {
    "dev": "deno run --watch --allow-net --allow-read main.ts",
    "start": "deno run --allow-net --allow-read main.ts",
    "test": "deno test --allow-read",
    "lint": "deno lint",
    "fmt": "deno fmt"
  },
  "imports": {
    "std/": "https://deno.land/[email protected]/",
    "oak": "https://deno.land/x/[email protected]/mod.ts"
  },
  "compilerOptions": {
    "strict": true
  }
}

The tasks section defines scripts similar to npm scripts. Run them with:

deno task dev
deno task test

The imports section creates import aliases (an import map), so instead of writing full URLs in every file, you write:

import { Application } from "oak";

Verify your configuration is valid:

deno info

Using npm Packages in Deno

Deno supports importing npm packages directly using the npm: specifier. This means you can use most of the npm ecosystem without switching runtimes:

import express from "npm:express@4";

const app = express();

app.get("/", (_req, res) => {
  res.json({ runtime: "deno", status: "running" });
});

app.listen(3000, () => {
  console.log("Server running on http://localhost:3000");
});

Run it with network permissions:

deno run --allow-net --allow-read --allow-env server.ts

Verify by opening http://localhost:3000 in a browser or with curl.

Deno vs Node.js – Practical Comparison

Here is how the two runtimes stack up in day-to-day usage:

FeatureNode.jsDeno
TypeScriptRequires tsc or ts-nodeNative, zero config
Package managementnpm/yarn with node_modulesURL imports, global cache
SecurityFull system access by defaultNo access unless granted
Linting/FormattingInstall ESLint, PrettierBuilt-in (deno lint, deno fmt)
TestingInstall Jest, Mocha, etc.Built-in (deno test)
npm compatibilityNativeVia npm: specifier (good, not perfect)
Ecosystem sizeMassiveGrowing, plus npm compat
Production maturity15+ yearsMaturing rapidly

Node.js remains the safer choice for large production applications with complex dependency trees. Deno shines for new projects, scripts, CLI tools, and situations where security isolation matters. The npm compatibility layer makes migration easier than it was in Deno’s early days.

Wrapping Up

Deno offers a cleaner developer experience than Node.js for TypeScript-heavy projects, with security defaults that make sense for modern deployments. Installation is a single command on both RHEL 10 and Ubuntu 24.04, the permissions model protects against supply-chain attacks, and deno.json gives you project configuration without the sprawl of package.json, tsconfig.json, and .eslintrc. If you are starting a new project or building internal tooling, Deno is worth serious consideration.

LEAVE A REPLY

Please enter your comment!
Please enter your name here