Add Caddy Server Support Alongside Nginx (#600)

* added enum

* add config for caddy

* add svg icon

* add caddy service class

* wip

* install caddy

* create base Caddyfile with common snippets

* Create a systemd service to run Caddy in the background.

* create uninstall file

* wip

* create path

* create vhost

* get vhost

* delete site

* add php version change file

* add custom ssl

* create redirect file

* add vhost for caddy site & load balancer

* update svg

* fix caddy icon

* fix style

* add systemctl reload method

* Reload systemd after modifying the Caddy service file.

* add caddy

* added tests

* format with pint

* prevent multiple web server installations

* added error log & access log

(cherry picked from commit 2318e1b1df)
This commit is contained in:
Rasel Islam Rafi
2025-05-29 15:25:36 +06:00
committed by Saeed Vaziry
parent 61506ff70e
commit 984c1f3a8e
24 changed files with 590 additions and 18 deletions

View File

@ -0,0 +1,19 @@
[Unit]
Description=Caddy web server
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,59 @@
{
# Global Errors Log
log {
output file /var/log/caddy/errors.log {
roll_size 100MB
roll_keep 10
roll_keep_for 720h # 30 days
}
format json {
time_format iso8601
}
level ERROR
exclude http.log.access
}
}
# Common snippets
(access_log) {
log {
output file /var/log/caddy/{args[0]}-access.log {
roll_size 100MB
roll_keep 10
roll_keep_for 720h # 30 days
}
format json {
time_format iso8601
}
}
}
(security_headers) {
header {
# Remove server and software information
-Server
-X-Powered-By
-Via
# Security headers
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
X-XSS-Protection "1; mode=block"
Content-Security-Policy "upgrade-insecure-requests"
# Enable compression
defer
}
}
(compression) {
encode {
gzip 6
zstd
minimum_length 1024
}
}
import sites-enabled/*

View File

@ -0,0 +1,9 @@
if ! sudo sed -i 's/php{{ $oldVersion }}/php{{ $newVersion }}/g' /etc/caddy/sites-available/{{ $domain }}; then
echo 'VITO_SSH_ERROR' && exit 1
fi
if ! sudo service caddy restart; then
echo 'VITO_SSH_ERROR' && exit 1
fi
echo "PHP Version Changed to {{ $newVersion }}"

View File

@ -0,0 +1,13 @@
if ! sudo mkdir -p {{ $path }}; then
echo 'VITO_SSH_ERROR' && exit 1
fi
if ! echo "{{ $certificate }}" | sudo tee {{ $certificatePath }}; then
echo 'VITO_SSH_ERROR' && exit 1
fi
if ! echo "{{ $pk }}" | sudo tee {{ $pkPath }}; then
echo 'VITO_SSH_ERROR' && exit 1
fi
echo "Successfully received certificate."

View File

@ -0,0 +1,7 @@
export DEBIAN_FRONTEND=noninteractive
rm -rf {{ $path }}
mkdir {{ $path }}
chmod -R 755 {{ $path }}

View File

@ -0,0 +1,7 @@
if ! sudo ln -s /etc/caddy/sites-available/{{ $domain }} /etc/caddy/sites-enabled/; then
echo 'VITO_SSH_ERROR' && exit 1
fi
if ! sudo service caddy restart; then
echo 'VITO_SSH_ERROR' && exit 1
fi

View File

@ -0,0 +1,7 @@
rm -rf {{ $path }}
sudo rm /etc/caddy/sites-available/{{ $domain }}
sudo rm /etc/caddy/sites-enabled/{{ $domain }}
echo "Site deleted"

View File

@ -0,0 +1 @@
cat /etc/caddy/sites-available/{{ $domain }}

View File

@ -0,0 +1,20 @@
# Add Caddy's GPG key and repository
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \
sudo tee /etc/apt/sources.list.d/caddy-stable.list
# Install required packages
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y \
debian-keyring debian-archive-keyring apt-transport-https curl
# Update package list
sudo DEBIAN_FRONTEND=noninteractive apt-get update -y
# Install Caddy
sudo DEBIAN_FRONTEND=noninteractive apt-get install caddy -y
sudo mkdir /etc/caddy/sites-available
sudo mkdir /etc/caddy/sites-enabled

View File

@ -0,0 +1,3 @@
@foreach($site->activeRedirects as $redirect)
redir {{ $redirect->from }} {{ $redirect->to }} {{ $redirect->mode }}
@endforeach

View File

@ -0,0 +1,12 @@
sudo service caddy stop
sudo DEBIAN_FRONTEND=noninteractive sudo apt remove caddy -y
sudo rm -rf /etc/caddy
sudo rm -rf /var/log/caddy
sudo rm -rf /var/lib/caddy
sudo rm -rf /var/cache/caddy
sudo rm -rf /usr/share/caddy
sudo rm -rf /etc/systemd/system/caddy.service
sudo systemctl daemon-reload

View File

@ -0,0 +1,47 @@
{{ $site->domain }} {{ $site->getAliasesString() }} {
@if ($site->activeSsl)
tls {{ $site->activeSsl->certificate_path }} {{ $site->activeSsl->pk_path }}
@endif
@if ($site->activeSsl && $site->force_ssl)
redir @http https://{host}{uri} permanent
@endif
import access_log {{ $site->domain }}
import compression
import security_headers
@if ($site->type()->language() === 'php')
root * {{ $site->getWebDirectoryPath() }}
@php
$phpSocket = "unix//var/run/php/php{$site->php_version}-fpm.sock";
if ($site->isIsolated()) {
$phpSocket = "unix//run/php/php{$site->php_version}-fpm-{$site->user}.sock";
}
@endphp
try_files {path} {path}/ /index.php?{query}
php_fastcgi {{ $phpSocket }}
file_server
@endif
@if ($site->type === \App\Enums\SiteType::LOAD_BALANCER)
reverse_proxy {
@if ($site->loadBalancerServers()->count() > 0)
@foreach($site->loadBalancerServers as $server)
to {{ $server->ip }}:{{ $server->port }}
@endforeach
@else
to 127.0.0.1
@endif
@switch($site->type_data['method'] ?? \App\Enums\LoadBalancerMethod::ROUND_ROBIN)
@case(\App\Enums\LoadBalancerMethod::LEAST_CONNECTIONS)
lb_policy least_conn
@break
@case(\App\Enums\LoadBalancerMethod::IP_HASH)
lb_policy ip_hash
@break
@default
lb_policy round_robin
@endswitch
header_up Host {host}
header_up X-Real-IP {remote}
}
@endif
@include('ssh.services.webserver.caddy.redirects', ['site' => $site])
}