# The Process Behind Using curl | bash for NexoralDNS One-Line Install

As a software engineer, I strongly believe in one thing:

> **If your user has to read documentation before using your product, you already lost them.**

That belief is the reason NexoralDNS can be installed using a single command:

```plaintext
curl -fsSL https://raw.githubusercontent.com/nexoral/NexoralDNS/main/Scripts/install.sh | bash
```

But this post is **not marketing**.

This is me explaining—*as a developer*—what actually happens when someone runs this command, why it’s safe (when done correctly), and how I designed the installer to make users do **less work, not more**.

---

## Why I Even Chose `curl | bash`

Let’s be honest.

Most engineers are suspicious of `curl | bash`.  
And they should be.

So why did I still choose it?

Because:

* My target users are **sysadmins, devs, and homelab users**
    
* NexoralDNS touches **networking, DNS, ports, and resolvers**
    
* Manual setup would be painful and error-prone
    
* Consistency matters more than purity
    

The goal wasn’t *zero magic*.  
The goal was **predictable automation**.

---

## Breaking Down the Command (No Myths)

Let’s split it:

```plaintext
curl -fsSL <url> | bash
```

### What `curl` Does Here

* `-f` → fail silently on HTTP errors
    
* `-s` → silent mode (no progress spam)
    
* `-S` → still show errors if something fails
    
* `-L` → follow redirects (GitHub raw URLs need this)
    

So effectively:

> “Download this script **only if it succeeds**, otherwise stop.”

No partial downloads. No HTML pages piped into bash.

---

### What the Pipe (`|`) Actually Means

The pipe does **not** magically give root access.

It simply means:

* `curl` outputs text (the script)
    
* `bash` reads that text from STDIN
    
* Bash executes it **line by line**
    

Equivalent to:

```plaintext
curl file.sh
bash file.sh
```

Just without creating a temporary file.

---

## My Core Installer Philosophy

Before writing a single line of this script, I decided:

1. **Fail early**
    
2. **Explain everything**
    
3. **Never assume system state**
    
4. **Undo changes on stop/remove**
    
5. **Networking safety &gt; convenience**
    

That mindset shaped the entire installer.

---

## Step 1: System Compatibility Checks (Before Touching Anything)

The script starts by answering one question:

> *“Should this system even be allowed to continue?”*

It checks:

* Linux only (no macOS, no WSL tricks)
    
* Debian-based distros only (Ubuntu, Debian, Mint, Zorin)
    
* Presence of `apt`
    
* Minimum **2GB RAM**
    
* Minimum **10GB disk**
    

Why?

Because DNS is **infrastructure**, not a toy.  
Failing halfway through setup is worse than refusing early.

---

## Step 2: Port Safety (DNS Is Special)

NexoralDNS needs:

* **53 (UDP)** → DNS
    
* **4000** → Admin Web UI
    
* **4773** → Internal broker
    

Before anything starts:

* The script checks if these ports are already in use
    
* Uses `lsof` or `ss`
    
* Hard-fails if any are occupied
    

Why I’m strict here:

> Binding to port 53 while another resolver is running will silently break DNS.

Silent failures in networking are deadly.

---

## Step 3: systemd-resolved (The Most Dangerous Part)

This is the part most installers get wrong.

On modern Linux:

* `systemd-resolved` **already listens on port 53**
    
* `/etc/resolv.conf` is often a **symlink**
    
* Blindly overwriting it breaks networking
    

So my script:

* Detects if `systemd-resolved` is running
    
* **Stops and disables it only when required**
    
* Frees port 53 cleanly
    
* Restores it on `stop` or `remove`
    

This is also why uninstalling NexoralDNS **restores your DNS**, not breaks it.

That took time to get right.

---

## Step 4: Docker Before DNS (Very Intentional)

Here’s a subtle but important decision:

> **All Docker images are pulled before DNS is disabled.**

Why?

Because Docker pulls need DNS.  
If I disabled the resolver first, image pulls would fail.

So the flow is:

1. Pull MongoDB, Redis, RabbitMQ, NexoralDNS image
    
2. Then disable system resolver
    
3. Then start containers
    

This small sequencing detail prevents a massive class of bugs.

---

## Step 5: Why Docker at All?

I didn’t choose Docker because it’s trendy.

I chose it because:

* DNS servers must be reproducible
    
* Networking state must be controlled
    
* Dependencies must be versioned
    
* Updates must be reversible
    

Docker gives me:

* Predictable runtime
    
* Safe upgrades
    
* Clean uninstall
    
* Zero host pollution
    

For infra software, this matters.

---

## Step 6: Version-Aware Updates (Not Blind Pulls)

The installer:

* Fetches a remote `VERSION` file
    
* Compares semantic versions
    
* Updates **only if remote &gt; local**
    
* Avoids unnecessary restarts
    

This matters because:

* DNS downtime is real downtime
    
* Restarting unnecessarily is irresponsible
    

---

## Step 7: DHCP Awareness (This Was Personal Curiosity)

DNS servers break when IPs change.

So the script:

* Detects the machine’s **active DHCP IP**
    
* Updates `/etc/resolv.conf` to point to itself
    
* Warns the user to set a **static IP**
    
* Uses internal messaging to rebind if IP changes
    

This came from my own experiments:

> “What happens if the DNS server IP changes mid-run?”

Now I know. And I coded for it.

---

## Step 8: `start`, `stop`, `update`, `remove` Are First-Class

This installer is not “run once and forget”.

It supports:

```plaintext
bash install.sh start
bash install.sh stop
bash install.sh update
bash install.sh remove
```

Each command:

* Manages DNS safely
    
* Restores system state
    
* Never leaves the system half-configured
    

Uninstalling does **not** leave broken DNS behind.  
That was non-negotiable.

---

## Why I Built It This Way

As an engineer, I hate installers that:

* Assume too much
    
* Don’t clean up
    
* Break networking
    
* Require manual fixes after uninstall
    

So I built the opposite.

The one-liner exists so users:

* Don’t read 10 pages of docs
    
* Don’t debug port conflicts
    
* Don’t fight DNS
    
* Don’t understand Docker internals
    

They just get a working DNS server.

---

## Final Thought

Yes, `curl | bash` can be dangerous.

But **opaque scripts are dangerous**, not the pattern itself.

That’s why NexoralDNS’s installer is:

* Open source
    
* Explicit
    
* Defensive
    
* Reversible
    
* Designed with networking respect
    

Automation is not about hiding complexity.  
It’s about **absorbing it responsibly**.
