Posted in

Caddy Web Server

Introduction to Caddy

Caddy is a powerful, enterprise-ready, open-source web server with automatic HTTPS. It is known for its simplicity, flexibility, and security features. Caddy automatically manages SSL certificates using Let’s Encrypt and provides easy configuration with its user-friendly Caddyfile syntax.

Whether you’re serving a single site, multiple domains, or configuring advanced proxy settings, Caddy offers a range of options to meet your needs. Proper configuration and maintenance, including using Certbot for SSL certificates if desired, ensure your server runs securely and efficiently.

Installing Caddy

Installing Caddy is straightforward across different Linux distributions. Here’s how to do it on some popular distros:

Ubuntu/Debian:

sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

CentOS/RHEL:

sudo yum install yum-plugin-copr
sudo yum copr enable @caddy/caddy
sudo yum install caddy

Fedora:

sudo dnf copr enable @caddy/caddy
sudo dnf install caddy

Once installed, you can start Caddy:

sudo systemctl start caddy
Basic Configuration

Caddy’s configuration is managed using a file called Caddyfile, typically located in /etc/caddy/. Here’s a simple configuration example to serve a static website:

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

Serving a Single Website
To serve a single website, place your website files in the root directory specified in the Caddyfile. Ensure the proper permissions are set:

sudo mkdir -p /var/www/html
sudo chown -R www-data:www-data /var/www/html
sudo chmod -R 755 /var/www/html

Restart Caddy to apply the changes:

sudo systemctl restart caddy

Serving Multiple Websites
Caddy can serve multiple websites using multiple site blocks in the Caddyfile. Here’s an example configuration for two websites:

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

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

Set permissions for each document root directory:

sudo mkdir -p /var/www/site1 /var/www/site2
sudo chown -R www-data:www-data /var/www/site1 /var/www/site2
sudo chmod -R 755 /var/www/site1 /var/www/site2

Restart Caddy to apply the changes:

sudo systemctl restart caddy
Configuring Reverse Proxy

To configure Caddy as a reverse proxy for multiple domains, use the reverse_proxy directive in the Caddy file for each domain. Here’s an example:

# Reverse proxy for site1.com
site1.com {
tls email@example.com
reverse_proxy backend1:80
}

# Reverse proxy for site2.com
site2.com {
tls email@example.com
reverse_proxy backend2:80
}

Replace backend1:80 and backend2:80 with the actual addresses and ports of your backend servers. Also, replace email@example.com with your actual email address for Let’s Encrypt certificate management.

Restart Caddy to apply the changes:

sudo systemctl restart caddy
Configuring Forward Proxy

Caddy can also be configured as a forward proxy using the forwardproxy plugin. First, you need to install the plugin. Then, configure it in the Caddyfile:

Install Forward Proxy Plugin:
You need to download a Caddy binary with the forwardproxy plugin or build Caddy with the plugin.

Configure Forward Proxy:

:8080 {
forwardproxy {
basic_auth user pass
}
}

Restart Caddy to apply the changes:

sudo systemctl restart caddy
Advanced Configuration Options

Caddy supports various advanced configurations such as URL rewriting, load balancing, and caching.

The following advanced configurations in Caddy provide powerful tools to manage various aspects of web server operations, from security and performance to URL management and user experience enhancements.

1. URL Rewriting

URL rewriting is useful when you want to change the URL structure without altering the content structure, such as redirecting outdated URLs to new ones or providing cleaner URLs.

Configuration Example:

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

@oldpage {
path /oldpage.html
}
rewrite @oldpage /newpage.html
}

root * /var/www/html: Specifies the root directory for the website files.
file_server: Enables serving static files from the root directory.
@oldpage: Defines a named matcher for the path /oldpage.html.
rewrite @oldpage /newpage.html: Rewrites requests from /oldpage.html to /newpage.html.

2. Load Balancing
Load balancing is used to distribute incoming network traffic across multiple servers to ensure no single server bears too much load, improving reliability and performance.

Configuration Example:

example.com {
reverse_proxy /api/* {
to http://backend1:8080 http://backend2:8080 http://backend3:8080
lb_policy random
}
}

reverse_proxy /api/*: Configures a reverse proxy for all paths starting with /api/.
to http://backend1:8080 http://backend2:8080 http://backend3:8080: Specifies backend servers.
lb_policy random: Sets the load balancing policy to randomly distribute requests among the backend servers.

3. Caching

Caching improves website performance by storing copies of files or responses so that future requests for those resources can be served faster.

Configuration Example:

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

route {
try_files {path} {path}/ /index.html
}

route /api/* {
reverse_proxy http://api_backend:8080
}

@cacheable {
path_regexp cacheable \.(html|css|js|png|jpg|jpeg|gif|svg|woff|woff2)$
}
header @cacheable Cache-Control "public, max-age=31536000"
}

route: Defines a sequence of handlers.
try_files {path} {path}/ /index.html: Tries to serve the requested file, directory, or falls back to index.html.
@cacheable: Uses a regular expression to match cacheable file types.
header @cacheable Cache-Control “public, max-age=31536000”: Adds a Cache-Control header to cacheable files.

4. HTTPS with Automatic Certificate Management

Enables HTTPS to secure data transmission and manage SSL/TLS certificates automatically.

Configuration Example:

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

tls {
issuer acme {
email your-email@example.com
}
}
}

tls: Enables TLS (HTTPS).
issuer acme: Uses ACME protocol for certificate management.
email your-email@example.com: Email for certificate notifications.

5. Basic Authentication
Protects specific parts of a website with a username and password, useful for admin panels or private content.

Configuration Example:

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

@protected {
path /admin/*
}
basicauth @protected {
username hashed_password
}
}

@protected: Defines a named matcher for the path /admin/*.
basicauth @protected { username hashed_password }: Configures basic authentication for the matched path.

6. IP Whitelisting
Restricts access to certain IP addresses, useful for securing admin areas or limiting access to certain parts of a website.

Configuration Example:

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

@whitelist {
remote_ip 192.168.1.1 192.168.1.2
}
respond @whitelist "Access Denied" 403
}

@whitelist: Matches requests from specific IP addresses.
respond @whitelist “Access Denied” 403: Responds with a 403 status code for non-whitelisted IP addresses.

7. Custom Error Pages
Provides user-friendly error pages for specific HTTP status codes, improving the user experience during errors.

Configuration Example:

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

handle_errors {
@404 {
expression {http.error.status_code} == 404
}
rewrite @404 /404.html
file_server
}
}

handle_errors: Defines custom error handling.
@404: Matches 404 status code errors.
rewrite @404 /404.html: Serves a custom 404 error page.

8. Rate Limiting
Limits the number of requests a client can make in a given time period to protect against abuse and ensure fair usage.

Configuration Example:

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

rate_limit {
zone example {
key client.ip
events 20
window 1m
}
}
}

rate_limit: Configures rate limiting.
zone example: Defines a rate limiting zone.
key client.ip: Uses the client’s IP address as the key.
events 20: Allows 20 requests.
window 1m: Per 1 minute time window.

9. Redirects
Redirects old URLs to new URLs, useful for SEO or restructuring a site without breaking existing links.

Configuration Example:

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

@oldpath {
path /oldpath
}
redir @oldpath /newpath
}

@oldpath: Matches the old URL /oldpath.
redir @oldpath /newpath: Redirects requests from /oldpath to /newpath.

10. Header Manipulation
Modifies HTTP headers for responses, useful for security headers, custom headers, or controlling caching.

Configuration Example:

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

header {
X-Frame-Options "DENY"
X-Content-Type-Options "nosniff"
Referrer-Policy "no-referrer"
}
}

header: Configures custom HTTP headers.
X-Frame-Options “DENY”: Prevents clickjacking.
X-Content-Type-Options “nosniff”: Prevents MIME type sniffing.
Referrer-Policy “no-referrer”: Disables referrer information.

Security Considerations

Securing Caddy involves several best practices:

Automatic HTTPS: Caddy automatically handles SSL certificates with Let’s Encrypt.
Restrict Access: Use basicauth or jwt to restrict access to sensitive directories.
Using Certbot for SSL Certificates

Securing Caddy involves implementing several best practices to ensure that your web server is protected against potential threats. Below, I’ll explain each of the best practices and provide detailed configurations and use cases for each option:

1. Automatic HTTPS with Caddy
Caddy is known for its automatic HTTPS feature, which simplifies the process of obtaining and renewing SSL certificates using Let’s Encrypt.

Configuration:
Caddy automatically handles SSL certificates if you specify your domain in the Caddyfile. Here’s a basic example:

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

Use Case:

Ideal for users who want a hassle-free setup for HTTPS without manually managing SSL certificates.
Suitable for small to medium-sized websites where ease of configuration and automatic renewal are priorities.

2. Restrict Access Using basicauth or jwt
To secure sensitive directories, you can use basicauth or jwt (JSON Web Tokens) to restrict access.

Configuration for basicauth

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

basicauth /admin {
admin JDJhJDE0JFZKZjBnQmUuLzNpVkpDZGhNTjlnSUZWSzVvQ1hlS2FXbFZVSVpVdUJja1lqbk4wMndrbzZZ
}
}

The string after admin is a bcrypt-hashed password.

Use Case:

Use basicauth for simple username/password protection.
Suitable for small websites or administrative areas where you need to restrict access to specific users.

Configuration for jwt -> Caddyfile:

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

jwt {
primary yes
trusted_tokens {
static_secret {
token_name access_token
token_secret my_secret_key
}
}
}

route /admin* {
jwt {
allow roles admin
}
reverse_proxy /admin http://localhost:8080
}
}

Use Case:

Use jwt for more advanced authentication scenarios involving token-based authentication.
Suitable for APIs or applications requiring robust security with role-based access control.

3. Using Certbot with Caddy
While Caddy’s automatic HTTPS is convenient, you might prefer to use Certbot for SSL certificates, especially if you have an existing workflow with Certbot.

Install Certbot:
Ubuntu/Debian:

sudo apt update
sudo apt install certbot

CentOS/RHEL:

sudo yum install certbot

Fedora:

sudo dnf install certbot

Obtain SSL Certificate:

sudo certbot certonly --webroot -w /var/www/html -d yourdomain.com -d www.yourdomain.com

Configure Caddy for SSL:

example.com {
root * /var/www/html
file_server
tls /etc/letsencrypt/live/yourdomain.com/fullchain.pem /etc/letsencrypt/live/yourdomain.com/privkey.pem
}

Use Case:

When you need more control over your SSL certificates and prefer to use Certbot.
Useful for complex environments or when integrating with existing Certbot-managed certificates.

4. Auto-Renew SSL Certificate:
Certbot sets up a cron job to automatically renew certificates. Verify it’s working correctly with:

sudo systemctl status certbot.timer

Use Case:

Ensures that your SSL certificates are always up to date without manual intervention.
Critical for production environments where uninterrupted HTTPS availability is essential.
Summary
Automatic HTTPS: Easiest option, fully managed by Caddy.
Restrict Access: Use basicauth for simple cases, jwt for advanced scenarios.
Certbot with Caddy: When more control over SSL management is required.
Auto-Renew: Ensures continuous certificate validity.

Leave a Reply

Your email address will not be published. Required fields are marked *