How To Install Caddy on Ubuntu 26.04 LTS

Install Caddy on Ubuntu 26.04

Caddy gives you a clean way to run a web server with automatic HTTPS and a simple config file. If you want to Install Caddy on Ubuntu 26.04 without guesswork, this guide walks you through the full setup, why each command matters, and how to verify that it works. The goal is not just to make it run, but to help you understand the system like a real sysadmin would.

Caddy is a strong fit for developers and Linux admins because it reduces certificate work and keeps server config readable. In a typical Caddy on Ubuntu 26.04 setup, you install it from the official repository, start the service, open the right firewall ports, then define a site block in the Caddyfile. That same flow also supports static sites and reverse proxy apps, so this Linux server tutorial stays useful beyond a basic install.

Prerequisites

Before you begin, make sure you have the right base setup. These items keep the install clean and reduce avoidable errors later.

  • Ubuntu 26.04 LTS server or VM.
  • Sudo access or root access.
  • A registered domain name if you want public HTTPS.
  • Open network access for ports 80 and 443.
  • A terminal client such as SSH, Windows Terminal, or local console.
  • Basic comfort with editing files in a Linux shell.

Step 1: Update Your System

Why this matters

Start by refreshing your package lists and applying updates. This lowers the chance of broken dependencies and gives you a cleaner base for the Caddy install.

sudo apt update
sudo apt upgrade -y

apt update refreshes the package index. apt upgrade -y installs the latest available updates. On a fresh server, this step often prevents small package issues from turning into install failures later.

Expected output

Reading package lists... Done
Building dependency tree... Done
Calculating upgrade... Done

Step 2: Install Required Tools

Why this matters

Caddy’s official package repo uses HTTPS and signed packages, so your system needs helper tools for secure repository setup. These packages support key handling, transport, and fetching the repo data.

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl

curl downloads the repository key and repo list. The keyring packages help Ubuntu trust the repository in a standard way. apt-transport-https makes sure apt can talk to HTTPS sources properly.

Step 3: Add the Caddy Repository

Why this matters

The official repository usually gives you a current and trusted Caddy version. That is better than relying on an old package from a default repo, especially for server software that depends on active maintenance.

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg

This command downloads Caddy’s signing key and stores it in a format apt can use. That matters because your system should verify who published the package before it installs anything.

Now add the repository source list.

curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list

This tells apt where to find Caddy packages. It keeps the vendor source separate from Ubuntu’s default package sources, which is cleaner and easier to manage.

Expected output

You should see a repo line written to the terminal, usually ending with a Caddy source entry.

Step 4: Install Caddy

Why this matters

Now that Ubuntu trusts the repo, refresh apt again so it can read the new package metadata. Then install the web server itself.

sudo apt update
sudo apt install -y caddy

The second apt update matters because apt cannot install from a repo it has not indexed yet. apt install caddy pulls in the binary, service unit, and default config files in one step.

Check the version

caddy version

This confirms the binary is installed and shows which release you are running. On a healthy install, you should see a version string such as 2.x.x.

Step 5: Start and Enable the Service

Why this matters

A web server should survive reboots without manual work. That is why systemd service management is part of a proper install, not an optional extra.

sudo systemctl enable caddy
sudo systemctl start caddy

enable makes Caddy start at boot. start launches it now so you can test it immediately. This is the standard production pattern for Linux services.

Verify service status

sudo systemctl status caddy

You want to see active (running) in the output.

● caddy.service - Caddy
     Loaded: loaded
     Active: active (running)

That status tells you the service started correctly and is ready to receive requests.

Step 6: Open the Firewall

Why this matters

Caddy can be installed perfectly and still fail to serve traffic if your firewall blocks the ports it needs. For public sites, port 80 helps with certificate handling, and port 443 carries encrypted traffic.

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status

If you use UFW, these rules let browsers reach Caddy and let Caddy complete automatic TLS challenges. Without them, HTTPS setup can fail even when the config is correct.

Expected output

Status: active
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere

Step 7: Create a Basic Caddyfile

Why this matters

The Caddyfile is the main config file for most Caddy setups. It keeps site config simple and readable, which is one of the biggest reasons admins like Caddy.

Back up the default file first.

sudo cp /etc/caddy/Caddyfile /etc/caddy/Caddyfile.bak

This gives you a safe rollback point. If a new config breaks, you can restore the old one fast.

Now edit the file.

sudo nano /etc/caddy/Caddyfile

For a simple static site, use this example.

example.com {
    root * /var/www/example.com
    file_server
}

This block tells Caddy to serve files from the site directory. It also tells Caddy to handle file delivery for visitors. If your domain points to the server and ports are open, Caddy can also handle HTTPS automatically.

Create the web root

sudo mkdir -p /var/www/example.com
sudo chown -R caddy:caddy /var/www/example.com

This creates a clean content directory and gives the Caddy service user access to it. That matters because file permission problems are a common cause of startup or access errors on Linux.

Add a test page

cat <<'EOF' | sudo tee /var/www/example.com/index.html
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Caddy on Ubuntu 26.04</title>
</head>
<body>
  <h1>Hello from Caddy</h1>
</body>
</html>
EOF

This gives you an easy way to confirm that the server is actually delivering content. A simple HTML test page isolates web server setup from application logic.

Step 8: Validate and Reload Caddy

Why this matters

Always validate the config before reloading. This catches syntax mistakes before they reach users.

sudo caddy fmt --overwrite /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile

caddy fmt keeps the file neat and consistent. caddy validate checks whether the config is valid, which helps you avoid downtime caused by a typo.

If validation passes, reload the service.

sudo systemctl reload caddy

Reloading applies the new config without a full stop-start cycle. That is safer for live systems.

Expected output

valid configuration

Step 9: Set Up Reverse Proxy

Why this matters

Many users install Caddy not just for static sites, but to place it in front of apps like Node.js, PHP-FPM, Python services, or Go APIs. A reverse proxy keeps the backend private while Caddy handles public traffic and TLS.

Edit the Caddyfile again.

sudo nano /etc/caddy/Caddyfile

Use this example for a local app on port 3000.

example.com {
    reverse_proxy 127.0.0.1:3000
}

This tells Caddy to forward web traffic to your app. The backend stays on localhost, which reduces exposure and keeps the public interface simpler. It also simplifies SSL handling, because Caddy terminates HTTPS at the edge.

Why localhost is better here

If your app only listens on 127.0.0.1, the internet cannot reach it directly. That adds a layer of protection and makes Caddy the only public entry point.

Reload again after saving.

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

Step 10: Check Everything From the Client Side

Why this matters

Server-side status is not enough. You should always test from a client machine to confirm the site works as users will see it.

curl -I https://example.com

If DNS, firewall, and TLS are correct, you should get an HTTP response header block with a success status such as 200 OK or a redirect if you configured one. Client-side checks help confirm that your public path is really working.

You can also inspect the loaded page in a browser and verify the lock icon. That confirms the server is serving HTTPS properly.

Troubleshooting Common Errors

1. Caddy will not start

Run:

sudo systemctl status caddy
sudo journalctl -u caddy -n 50 --no-pager

This usually points to a bad Caddyfile, a permission issue, or a port conflict. Logs matter because they tell you exactly where the startup failed.

2. Port 80 or 443 is already in use

Check what owns the port:

sudo ss -tulpn | grep -E ':80|:443'

If another service is listening there, Caddy cannot bind to the same port. Stop the other service or move it to a different port before retrying.

3. HTTPS certificate errors

Make sure your domain points to the server and that ports 80 and 443 are open. Caddy needs public reachability for automatic certificate setup on normal public domains. If DNS is wrong or the firewall blocks the request, certificate issuance can fail.

4. Permission denied on site files

Fix ownership or read permissions.

sudo chown -R caddy:caddy /var/www/example.com
sudo chmod -R 755 /var/www/example.com

This ensures the service account can read the web content. On Linux, the wrong owner or mode can break a site even when the config is correct.

5. Config changes do not appear

Always validate and reload.

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy

If the config fails validation, Caddy will not apply it. That behavior protects the server from bad changes, so treat validation as part of your normal workflow.

r00t is a Linux Systems Administrator and open-source advocate with over ten years of hands-on experience in server infrastructure, system hardening, and performance tuning. Having worked across distributions such as Debian, Arch, RHEL, and Ubuntu, he brings real-world depth to every article published on this blog. r00t writes to bridge the gap between complex sysadmin concepts and practical, everyday application — whether you are configuring your first server or optimizing a production environment. Based in New York, US, he is a firm believer that knowledge, like open-source software, is best when shared freely.

Related Posts