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:
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:
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:
curloutputs text (the script)bashreads that text from STDINBash executes it line by line
Equivalent to:
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:
Fail early
Explain everything
Never assume system state
Undo changes on stop/remove
Networking safety > 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
aptMinimum 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
lsoforssHard-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-resolvedalready listens on port 53/etc/resolv.confis often a symlinkBlindly overwriting it breaks networking
So my script:
Detects if
systemd-resolvedis runningStops and disables it only when required
Frees port 53 cleanly
Restores it on
stoporremove
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:
Pull MongoDB, Redis, RabbitMQ, NexoralDNS image
Then disable system resolver
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
VERSIONfileCompares semantic versions
Updates only if remote > 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.confto point to itselfWarns 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:
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.

