AlmaLinuxRHEL Based

How To Install Caddy on AlmaLinux 10

Install Caddy on AlmaLinux 10

Modern web servers need to be fast, secure, and simple to configure. Caddy stands out as an exceptional choice for AlmaLinux 10 environments, offering automatic HTTPS certificates, HTTP/3 support, and a remarkably straightforward configuration syntax. This comprehensive guide walks through every step of installing and configuring Caddy on AlmaLinux 10, from initial system preparation to deploying your first secure website. Whether you’re a system administrator seeking alternatives to traditional web servers or a developer looking for hassle-free SSL management, this tutorial provides everything needed to get Caddy running smoothly on your AlmaLinux 10 server.

What is Caddy Web Server?

Caddy is an open-source, enterprise-ready web server written in the Go programming language. Released in 2015, it has rapidly gained popularity among developers and system administrators for its revolutionary approach to web server management. The server’s primary philosophy centers on simplicity and security by default, eliminating the complex configuration files that plague traditional web servers.

Unlike Apache or Nginx, Caddy automatically obtains and renews SSL/TLS certificates without any manual intervention. This feature alone has made it a favorite for developers who want secure websites without wrestling with certificate authorities and renewal scripts. The Go language provides Caddy with exceptional memory safety, efficient concurrency handling, and cross-platform compatibility across Linux, Windows, and macOS systems.

Caddy serves production environments reliably, powering thousands of websites globally. The active community and regular updates ensure compatibility with the latest web standards and security protocols. Modern protocols like HTTP/3 and QUIC are built directly into Caddy, providing cutting-edge performance without requiring additional modules or compilation.

Key Features and Benefits of Caddy

Automatic HTTPS with Let’s Encrypt represents Caddy’s most celebrated feature. The web server automatically obtains, installs, and renews SSL/TLS certificates from Let’s Encrypt without any configuration. Simply specify your domain name in the Caddyfile, and Caddy handles the entire certificate lifecycle automatically.

Simple Caddyfile configuration replaces the cryptic syntax of traditional web servers with human-readable directives. The Caddyfile uses intuitive, natural language that makes sense even to beginners. Configuration changes are straightforward, reducing the learning curve significantly compared to Apache’s httpd.conf or Nginx’s server blocks.

HTTP/3 and QUIC protocol support comes enabled by default in Caddy. These modern protocols improve website performance, especially on mobile networks and high-latency connections. The built-in support means no compilation flags, external modules, or complex configuration required.

Built-in reverse proxy capabilities allow Caddy to function as a load balancer and application gateway. The reverse proxy configuration uses simple directives to route traffic to backend applications, supporting WebSocket connections, health checks, and automatic failover. This makes Caddy ideal for microservices architectures and containerized deployments.

Minimal resource consumption stems from Go’s efficient memory management and concurrency model. Caddy typically uses less RAM than Apache while handling similar traffic loads. The single binary deployment eliminates dependency conflicts and simplifies updates across multiple servers.

Cross-platform compatibility ensures Caddy runs identically across different operating systems. Development on macOS or Windows translates seamlessly to production Linux deployments. The consistent behavior across platforms reduces deployment surprises and environment-specific bugs.

Extensibility through plugins provides additional functionality when needed. The modular architecture allows adding features like authentication, database integration, or custom middleware without bloating the core server. Community-developed plugins extend Caddy’s capabilities for specialized use cases.

Integrated file server handles static content efficiently with automatic directory browsing, content negotiation, and compression. The file server requires minimal configuration while providing features that would require multiple directives in other web servers.

Prerequisites and Requirements

Before beginning the Caddy installation on AlmaLinux 10, ensure your system meets the following requirements. A fresh or existing AlmaLinux 10 installation provides the foundation for this tutorial. The server must be accessible via SSH with root or sudo privileges for executing administrative commands.

Minimum hardware requirements include 1 GB RAM, though 2 GB or more is recommended for production environments. At least 10 GB of disk space should be available, with 20 GB recommended to accommodate logs, certificates, and website content. A 64-bit processor (x86_64 architecture) is required for running modern Caddy versions.

The firewalld service should be installed and running for managing network access rules. Basic firewall configuration knowledge helps secure your server while allowing necessary web traffic. A stable internet connection enables package downloads and certificate acquisition from Let’s Encrypt.

Optionally, having a registered domain name with DNS A record pointing to your server’s IP address enables automatic HTTPS functionality. Basic command-line familiarity helps navigate the terminal and edit configuration files. Text editors like vi, vim, or nano should be available for configuration file modifications.

Step 1: Update Your AlmaLinux 10 System

System updates ensure all packages contain the latest security patches and bug fixes before installing new software. Updating also resolves potential dependency conflicts that could interfere with Caddy installation. Open your terminal and execute the following command to update all installed packages:

sudo dnf update -y

The DNF package manager downloads and installs available updates across your system. This process may take several minutes depending on how many packages require updates and your internet connection speed. The -y flag automatically answers “yes” to confirmation prompts, streamlining the update process.

After updates complete, verify your AlmaLinux version to confirm you’re running AlmaLinux 10:

cat /etc/almalinux-release

The EPEL (Extra Packages for Enterprise Linux) repository typically comes pre-installed on AlmaLinux 10. If needed, install it with:

sudo dnf install epel-release -y

Understanding the DNF package manager proves valuable for ongoing system maintenance. DNF replaced YUM in newer Red Hat-based distributions, offering improved performance, better dependency resolution, and more intuitive command syntax.

Step 2: Install DNF COPR Plugin

COPR (Cool Other Package Repo) is a Fedora project providing infrastructure for building and managing third-party package repositories. Many modern applications, including Caddy, distribute packages through COPR to reach users quickly with the latest releases. Installing the COPR plugin extends DNF’s functionality to work with these community repositories.

Execute the following command to install the DNF COPR plugin:

sudo dnf install 'dnf-command(copr)' -y

This command installs the necessary components for enabling and managing COPR repositories on your AlmaLinux 10 system. The installation typically completes within seconds, adding minimal overhead to your package management system.

COPR repositories undergo less rigorous testing than official AlmaLinux repositories, but they provide access to software not available through standard channels. The Caddy project maintains its COPR repository with regular updates and security patches. Understanding COPR’s role helps you make informed decisions about third-party software sources.

Security considerations for COPR repositories include verifying GPG signatures during package installation and monitoring official announcements for security updates. COPR repositories are managed by community members or project maintainers, making them generally trustworthy but requiring more vigilance than official repositories.

Step 3: Enable the Caddy COPR Repository

With the COPR plugin installed, enable the official Caddy repository to access the latest Caddy packages. The Caddy team maintains this repository, ensuring timely updates and compatibility with RHEL-based distributions like AlmaLinux.

Run the following command to enable the Caddy COPR repository:

sudo dnf copr enable @caddy/caddy

The system prompts you to confirm repository addition. Type y and press Enter to proceed. The repository metadata downloads, and GPG keys are imported for package verification. This security measure ensures downloaded packages are authentic and haven’t been tampered with.

After enabling the repository, refresh your system’s package cache to include Caddy packages:

sudo dnf update -y

Expected output includes messages about the Copr repository for Caddy being successfully enabled and metadata being synchronized. If you encounter repository errors, verify your internet connection and check that the COPR plugin installed correctly in the previous step.

Troubleshooting common repository issues involves checking DNS resolution, verifying firewall rules allow outbound HTTPS connections, and ensuring sufficient disk space for repository metadata. Repository mirrors occasionally experience downtime; waiting a few minutes and retrying usually resolves temporary connection issues.

Step 4: Install Caddy Web Server

Installing Caddy from the enabled COPR repository is straightforward using DNF’s familiar package management commands. The repository provides pre-compiled binaries optimized for Red Hat-based distributions, eliminating the need for manual compilation.

Execute the installation command:

sudo dnf install caddy -y

DNF resolves dependencies automatically and downloads the Caddy package. During installation, you’ll be asked to accept the repository’s GPG key if this is your first package installation from the Caddy COPR. Type y to accept and continue the installation process.

The installation creates several important directories and files. Configuration files are stored in /etc/caddy/, with the primary configuration file being /etc/caddy/Caddyfile. The Caddy binary installs to /usr/bin/caddy, making it accessible from any directory through your PATH.

Verify the successful installation by checking the installed Caddy version:

caddy version

This command displays the Caddy version number, build details, and Git commit hash. Seeing version information confirms Caddy installed correctly and is ready for configuration. The version command provides useful information when reporting issues or verifying compatibility with specific features.

Understanding Caddy’s installation directories helps with troubleshooting and maintenance. Default file locations include /var/lib/caddy for data storage and automatic certificate storage, and /usr/lib/systemd/system/caddy.service for the systemd service file. Log files typically go to /var/log/caddy when configured.

Step 5: Start and Enable Caddy Service

Caddy integrates with systemd, AlmaLinux’s service management system, allowing standard service control commands. Starting the Caddy service activates the web server, while enabling it ensures automatic startup after system reboots.

Start the Caddy service with:

sudo systemctl start caddy

Enable automatic startup on boot:

sudo systemctl enable caddy

Alternatively, combine both operations into a single command:

sudo systemctl enable --now caddy

Verify that Caddy is running correctly:

sudo systemctl status caddy

The status command displays detailed information about the service state. Look for “active (running)” in green text, indicating Caddy started successfully. The output also shows recent log entries, helpful for diagnosing startup issues.

Understanding systemd service management proves valuable for ongoing server administration. Common service commands include sudo systemctl stop caddy to halt the service, sudo systemctl restart caddy for a full restart, and sudo systemctl reload caddy for configuration changes without dropping connections.

The Caddy service file at /usr/lib/systemd/system/caddy.service defines how systemd manages Caddy. This file specifies the user account (caddy), working directory, and startup commands. Examining this file provides insights into Caddy’s execution environment and security settings.

Service logs are accessible through journalctl:

sudo journalctl -u caddy -f

This command displays real-time log output from the Caddy service, invaluable for troubleshooting configuration issues or monitoring traffic patterns. The -f flag follows the log, continuously displaying new entries.

Step 6: Configure Firewall Rules

AlmaLinux 10 includes firewalld by default, protecting your server by blocking unauthorized network access. Web servers require open ports for HTTP (80) and HTTPS (443) traffic to reach users’ browsers. Configuring firewall rules enables this necessary access while maintaining security.

Open HTTP port 80 for unencrypted traffic:

sudo firewall-cmd --add-port=80/tcp --permanent

Open HTTPS port 443 for encrypted traffic:

sudo firewall-cmd --add-port=443/tcp --permanent

These commands can be combined for efficiency:

sudo firewall-cmd --add-port={80,443}/tcp --permanent

The --permanent flag ensures rules persist across firewall and system restarts. Reload the firewall to activate the new rules:

sudo firewall-cmd --reload

Verify your firewall configuration:

sudo firewall-cmd --list-all

This command displays all active firewall rules, including the newly opened ports under the “ports:” section. Confirming the rules prevents confusion if web traffic fails to reach your server.

Alternative firewall configuration uses service names instead of port numbers:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

This method proves more readable and automatically handles any future port changes in service definitions. Both approaches achieve the same result; choose based on personal preference.

SELinux considerations may require additional configuration in security-hardened environments. By default, SELinux should permit Caddy to bind to ports 80 and 443. Custom port usage requires SELinux policy modifications, which fall outside this basic installation guide.

Step 7: Verify Caddy Installation

Testing confirms Caddy is installed, running, and accessible from external connections. Multiple verification methods ensure complete functionality before proceeding with advanced configuration.

Test locally using curl:

curl http://localhost

This command fetches the default Caddy welcome page from the local server. Successful output displays HTML content from Caddy’s default response. Local testing verifies Caddy responds to requests without involving firewall or network routing.

Test externally by opening a web browser and navigating to your server’s IP address:

http://your-server-ip

Replace your-server-ip with your actual server IP address. The Caddy default page appears if everything is configured correctly. External testing confirms firewall rules allow incoming connections and Caddy binds to the public interface.

Check Caddy logs for detailed diagnostic information:

sudo journalctl -u caddy --no-pager | tail -50

Log entries show Caddy’s startup process, listening addresses, and any errors encountered. Analyzing logs helps identify configuration problems or permission issues preventing normal operation.

Troubleshooting connection issues typically involves checking service status, verifying firewall rules, and ensuring no conflicting services occupy ports 80 or 443. Common conflicts include Apache or Nginx running simultaneously with Caddy. Stop competing web servers before starting Caddy.

Common error messages include “address already in use,” indicating another service occupies the required port. Identify the conflicting process with sudo netstat -tlnp | grep :80 and stop it appropriately. Permission errors suggest the Caddy user lacks necessary file system access.

Step 8: Understanding the Caddyfile

The Caddyfile serves as Caddy’s primary configuration file, located at /etc/caddy/Caddyfile. Unlike traditional web servers with complex configuration syntax, the Caddyfile uses human-readable directives that clearly express intent. Understanding Caddyfile structure enables powerful configurations with minimal effort.

Basic Caddyfile structure consists of global options and site blocks. Global options affect all sites, while site blocks configure individual websites. The default Caddyfile includes commented examples demonstrating common patterns.

View the default Caddyfile:

sudo cat /etc/caddy/Caddyfile

Basic syntax follows this pattern:

example.com {
    directive1
    directive2 argument
}

Site blocks begin with domain names or IP addresses, followed by curly braces containing directives. Indentation improves readability but isn’t syntactically required. Comments start with # and extend to the line’s end.

Common directives include root for specifying the document root directory, file_server for enabling static file serving, reverse_proxy for proxying to backend applications, encode for compression, and log for access logging. These directives chain together to build complete configurations.

Validating Caddyfile syntax prevents runtime errors:

caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile

Successful validation returns no output or displays formatted configuration. Syntax errors show line numbers and descriptions, pinpointing problems quickly.

Format your Caddyfile for consistency:

caddy fmt --overwrite /etc/caddy/Caddyfile

This command automatically indents and organizes directives according to Caddy conventions. Well-formatted configurations are easier to read and maintain, especially in complex multi-site setups.

Best practices for Caddyfile organization include grouping related directives, using comments to explain complex logic, and separating concerns into multiple files when appropriate. Caddy supports importing external files, enabling modular configurations for large deployments.

Step 9: Create a Basic Website Configuration

Setting up your first website demonstrates Caddy’s simplicity while establishing patterns for future sites. This process involves creating directory structures, setting permissions, writing content, and configuring the Caddyfile.

Create the website directory structure:

sudo mkdir -p /var/www/example.com/html

Replace example.com with your actual domain name. The -p flag creates parent directories as needed, ensuring the complete path exists.

Set proper ownership for the Caddy user:

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

Correct ownership prevents permission errors when Caddy reads files. The recursive -R flag applies ownership to all files and subdirectories.

Create a dedicated log directory:

sudo mkdir -p /var/log/caddy
sudo chown caddy:caddy /var/log/caddy

Separate log directories organize server operations and simplify log analysis. Proper permissions allow Caddy to write access logs without root privileges.

Create a sample index.html file:

sudo nano /var/www/example.com/html/index.html

Add the following HTML content:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Welcome to Caddy on AlmaLinux 10</title>
</head>
<body>
    <h1>Success! Caddy is running on AlmaLinux 10</h1>
    <p>This is a test page demonstrating a working Caddy installation.</p>
</body>
</html>

Save and close the file. This minimal HTML provides visual confirmation when accessing your site.

Edit the Caddyfile to configure your site:

sudo nano /etc/caddy/Caddyfile

Add the following configuration, replacing example.com with your domain:

example.com {
    root * /var/www/example.com/html
    file_server
    encode gzip
    log {
        output file /var/log/caddy/example.com.log
    }
}

This configuration specifies the document root, enables file serving, applies gzip compression, and configures access logging. Each directive serves a specific purpose in delivering web content efficiently.

The root directive sets where Caddy finds website files. The asterisk matches all request paths, applying this root universally. The file_server directive activates static file serving with automatic directory indexing and content negotiation.

The encode gzip directive compresses responses, reducing bandwidth usage and improving page load times. Caddy automatically determines which files to compress based on content type. The log block directs access logs to a specific file for traffic analysis.

Validate your configuration before applying it:

caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile

Configuration validation catches syntax errors, preventing service failures. Successful validation indicates your Caddyfile is ready for deployment.

Step 10: Enable Automatic HTTPS

Caddy’s automatic HTTPS represents its most revolutionary feature, eliminating manual certificate management entirely. Proper configuration enables automatic certificate acquisition, installation, and renewal from Let’s Encrypt.

Prerequisites for automatic HTTPS include a valid domain name pointing to your server’s public IP address. DNS propagation must complete before certificate acquisition succeeds. Ports 80 and 443 must be accessible from the internet for Let’s Encrypt’s validation challenges.

Caddy automatically enables HTTPS when you specify a domain name in the Caddyfile. No additional configuration is required for basic setups. The first time you access your site over HTTPS, Caddy contacts Let’s Encrypt, proves domain ownership, and installs the issued certificate.

Optionally specify an email address for Let’s Encrypt notifications:

example.com {
    root * /var/www/example.com/html
    file_server
    encode gzip
    tls your-email@example.com
}

The email address receives expiration warnings if automatic renewal fails. Let’s Encrypt requires a valid email for account creation and certificate management.

Certificates are stored in /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/. Caddy manages this directory automatically; manual intervention is rarely necessary. Certificate renewal occurs automatically before expiration, typically around 30 days prior.

View certificate information:

sudo ls -la /var/lib/caddy/.local/share/caddy/certificates/acme-v02.api.letsencrypt.org-directory/

This directory contains certificates for all configured domains. Each domain has subdirectories for certificates, keys, and metadata.

Troubleshooting certificate issues involves checking DNS records, verifying firewall rules, and reviewing logs for Let’s Encrypt error messages. Common problems include DNS pointing to incorrect IP addresses, firewall blocking HTTP challenge validation, or rate limiting from excessive certificate requests.

Manual certificate specification is possible for custom certificates or internal certificate authorities. The tls directive accepts paths to certificate and key files:

example.com {
    tls /path/to/cert.pem /path/to/key.pem
}

This approach bypasses automatic certificate acquisition, useful for corporate environments with internal certificate authorities.

Step 11: Reload and Test Your Configuration

Applying configuration changes requires restarting or reloading the Caddy service. Reloading preserves existing connections while loading new configurations, minimizing service disruption.

Restart Caddy service completely:

sudo systemctl restart caddy

Full restarts drop all connections and reload everything from scratch. Use restarts when configuration changes are extensive or troubleshooting persistent issues.

Gracefully reload configuration without dropping connections:

sudo systemctl reload caddy

Reloading is preferred for configuration updates in production environments. Caddy applies changes while maintaining active connections, ensuring zero downtime for users.

Test your website with HTTPS enabled. Open your browser and navigate to:

https://example.com

The browser displays your website with a valid SSL certificate. Check the address bar for the padlock icon indicating secure HTTPS connection. Click the padlock to view certificate details, confirming Let’s Encrypt issued the certificate.

Verify SSL configuration quality using SSL Labs:

https://www.ssllabs.com/ssltest/analyze.html?d=example.com

SSL Labs performs comprehensive security testing, rating your SSL implementation from A+ to F. Caddy typically achieves A or A+ ratings with default configurations, demonstrating strong security practices.

Test compression with curl:

curl -H "Accept-Encoding: gzip" -I https://example.com

The response headers should include Content-Encoding: gzip, confirming compression works correctly. Compressed responses reduce bandwidth and improve load times significantly.

Performance testing verifies your server handles requests efficiently:

curl -o /dev/null -s -w "Time: %{time_total}s\n" https://example.com

This command measures total request time, providing baseline performance metrics. Compare results across configuration changes to measure optimization impact.

Advanced Configuration Options

Expanding beyond basic file serving, Caddy offers powerful features for complex deployments. Reverse proxy configuration forwards requests to backend applications, load balancing distributes traffic across multiple servers, and advanced directives customize behavior precisely.

Setting up a reverse proxy for backend applications:

example.com {
    reverse_proxy localhost:8080
}

This configuration proxies all requests to an application running on port 8080. Caddy handles SSL termination, forwarding decrypted traffic to the backend. Additional options include custom headers, load balancing, and health checks.

Configuring multiple domains within a single Caddyfile:

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

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

Each site block operates independently with separate configurations. This approach scales efficiently to dozens or hundreds of sites.

Adding custom headers enhances security and functionality:

example.com {
    header {
        Strict-Transport-Security "max-age=31536000;"
        X-Frame-Options "DENY"
        X-Content-Type-Options "nosniff"
    }
}

Security headers protect against common web vulnerabilities. HSTS forces HTTPS usage, X-Frame-Options prevents clickjacking, and X-Content-Type-Options stops MIME sniffing attacks.

Troubleshooting Common Issues

Resolving installation and configuration problems requires systematic diagnostic approaches. Understanding common issues accelerates problem resolution and minimizes downtime.

Port already in use errors indicate another service occupies ports 80 or 443. Identify conflicting processes:

sudo netstat -tlnp | grep ':80\|:443'

Stop conflicting services like Apache or Nginx before starting Caddy. Only one service can bind to a given port simultaneously.

Permission denied errors stem from incorrect file ownership or directory permissions. Verify the Caddy user owns website directories:

sudo chown -R caddy:caddy /var/www/your-site

Check directory permissions allow reading files:

sudo chmod -R 755 /var/www/your-site

Certificate acquisition failures usually result from DNS misconfiguration or firewall blocking. Verify DNS records resolve correctly:

nslookup your-domain.com

Ensure the returned IP address matches your server. Firewall rules must allow inbound connections on ports 80 and 443 for Let’s Encrypt challenges.

Caddy service fails to start often indicates Caddyfile syntax errors. Review the configuration:

caddy validate --adapter caddyfile --config /etc/caddy/Caddyfile

Check service logs for detailed error messages:

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

502 Bad Gateway errors with reverse proxies suggest backend applications aren’t running or aren’t listening on the specified port. Verify backend status and connectivity:

curl http://localhost:8080

If the backend doesn’t respond, the reverse proxy cannot forward requests successfully.

Security Best Practices

Maintaining server security requires ongoing vigilance and proactive measures. Following established security practices protects your infrastructure and user data.

Keep Caddy updated regularly by checking for new releases and applying updates promptly. Security patches address vulnerabilities discovered after release:

sudo dnf update caddy

Restrict file permissions to minimum necessary levels. Website files typically require 644 permissions for files and 755 for directories:

find /var/www/your-site -type f -exec chmod 644 {} \;
find /var/www/your-site -type d -exec chmod 755 {} \;

Use strong TLS configurations by keeping default Caddy settings, which implement current security best practices. Avoid weakening TLS settings unless specific compatibility requirements demand it.

Implement rate limiting to prevent abuse and denial-of-service attacks. Caddy supports rate limiting through the rate_limit directive in various configurations.

Regular security audits identify potential vulnerabilities before exploitation. Review access logs for suspicious patterns, monitor resource usage for anomalies, and keep informed about security advisories affecting your software stack.

Monitor logs systematically for unusual activity. Automated log analysis tools can alert administrators to potential security incidents in real-time.

Backup configurations regularly to facilitate quick recovery after incidents. Store backups securely, preferably off-site or in cloud storage with encryption.

Congratulations! You have successfully installed Caddy. Thanks for using this tutorial for installing the Caddy Web Server on AlmaLinux OS 10 system. For additional or useful information, we recommend you check the official Caddy website.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal!

r00t

r00t is an experienced Linux enthusiast and technical writer with a passion for open-source software. With years of hands-on experience in various Linux distributions, r00t has developed a deep understanding of the Linux ecosystem and its powerful tools. He holds certifications in SCE and has contributed to several open-source projects. r00t is dedicated to sharing her knowledge and expertise through well-researched and informative articles, helping others navigate the world of Linux with confidence.
Back to top button