서버 설정 · 9 min read · Nov 28, 2025
우분투 20.04에 PHP 및 MariaDB와 함께 Caddy 웹 서버 설치 및 구성하는 방법

Caddy 웹 서버는 GO 언어로 작성된 현대적인 오픈 소스 웹 서버입니다. 의존성이 없으며 정적 바이너리 파일로 실행되며 SSL 인증서를 자동으로 생성하고 갱신합니다. 정적 파일 서버, 확장 가능한 리버스 프록시 또는 강력한 동적 서버로 작동할 수 있으며 플러그인을 통해 확장할 수 있습니다. 또한 HTTP/2 및 실험적인 HTTP/3 프로토콜에 대한 지원도 포함되어 있습니다.
이 튜토리얼에서는 우분투 20.04 기반 서버에서 PHP 및 MariaDB와 함께 Caddy를 설치하고 구성합니다.
전제 조건
- sudo 권한이 있는 비 루트 계정을 가진 우분투 20.04 서버.
- 서버의 IP 주소를 가리키는 완전히 등록된 도메인 이름.
1단계 - 방화벽 구성
UFW(간단한 방화벽)를 사용하는 경우 서버가 작동하도록 HTTP 및 HTTPS 포트에 대한 액세스를 허용하도록 구성해야 합니다.
방화벽 상태를 확인합니다.
$ sudo ufw status
다음과 같은 내용을 볼 수 있어야 합니다.
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
HTTP 및 HTTPS 포트를 허용합니다.
$ sudo ufw allow http
$ sudo ufw allow https
확인을 위해 상태를 다시 확인합니다.
$ sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
2단계 - Caddy 설치
Caddy를 설치하는 방법에는 여러 가지가 있으며, 여기에는 도커 설치, 공식 리포지토리 사용 또는 소스에서 빌드하는 방법이 포함됩니다. 소스에서 빌드하는 방법은 3자 모듈/플러그인을 통해서만 추가할 수 있는 기능이 필요한 경우 유용합니다.
이 튜토리얼의 목적을 위해 우리는 우분투/데비안 기반 시스템을 위한 공식 Caddy 리포지토리를 사용하는 것으로 고정하겠습니다.
리포지토리를 목록에 추가합니다.
$ echo "deb [trusted=yes] https://apt.fury.io/caddy/ /" | sudo tee -a /etc/apt/sources.list.d/caddy-fury.list
$ sudo apt update
이렇게 하면 /etc/apt/sources.list.d 디렉토리에 Caddy의 리포지토리 위치가 포함된 caddy 리포지토리 파일이 생성됩니다.
Caddy를 설치합니다.
$ sudo apt install caddy
이렇게 하면 Caddy 웹 서버가 자동으로 설치되고 실행됩니다. 브라우저에서 http://를 열면 다음 페이지가 표시됩니다.

3단계 - PHP 설치
Ondrej의 PHP 리포지토리를 설치합니다.
$ sudo add-apt-repository ppa:ondrej/php
추가 패키지와 함께 PHP 7.4를 설치합니다.
$ sudo apt install php-cli php-fpm php-mysql
PHP가 제대로 작동하는지 확인합니다.
$ php --version
유사한 출력을 볼 수 있어야 합니다.
PHP 7.4.6 (cli) (built: May 14 2020 10:03:35) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.6, Copyright (c), by Zend Technologies
4단계 - MariaDB 설치
MariaDB는 MySQL의 드롭인 대체품으로, MariaDB를 실행하고 운영하는 명령은 MySQL과 동일합니다.
MariaDB의 공식 리포지토리를 추가합니다. MariaDB의 리포지토리 페이지에서 서버의 위치에 더 가까운 다른 미러를 선택할 수 있습니다.
$ sudo apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
$ sudo add-apt-repository 'deb [arch=amd64] http://mirror.lstn.net/mariadb/repo/10.4/ubuntu focal main'
MariaDB를 설치하려면 다음 명령을 실행합니다.
$ sudo apt install mariadb-server
MariaDB가 올바르게 설치되었는지 확인합니다.
$ mysql --version
다음 출력을 볼 수 있어야 합니다.
mysql Ver 15.1 Distrib 10.4.13-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
MariaDB 서비스를 활성화합니다.
$ sudo systemctl enable mariadb
5단계 - MariaDB 구성
다음 명령을 실행하여 루트 비밀번호 설정, 익명 사용자 제거, 원격 루트 로그인 금지 및 테스트 테이블 삭제와 같은 기본 구성을 수행합니다.
$ sudo mysql_secure_installation
MariaDB 10.4에서는 이제 루트 비밀번호 사용 또는 unix_socket 플러그인 사용 중에서 선택하라는 메시지가 표시됩니다. unix_socket 플러그인은 Linux 사용자 자격 증명으로 MariaDB에 로그인할 수 있게 해줍니다. 이는 더 안전하게 간주되지만 phpMyAdmin과 같은 3자 앱을 사용하려면 전통적인 사용자 이름/비밀번호가 필요합니다. 이 튜토리얼에서는 unix_socket 플러그인을 사용하겠습니다. 데이터베이스에 대해 생성한 특정 사용자로 phpMyAdmin을 여전히 사용할 수 있습니다.
Enter를 누르면 기본 옵션(이 경우 대문자 Y)이 선택됩니다.
NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!
In order to log into MariaDB to secure it, we'll need the current
password for the root user. If you've just installed MariaDB, and
haven't set the root password yet, you should just press enter here.
Enter current password for root (enter for none): [PRESS ENTER]
OK, successfully used password, moving on...
Setting the root password or using the unix_socket ensures that nobody
can log into the MariaDB root user without the proper authorisation.
You already have your root account protected, so you can safely answer 'n'.
Switch to unix_socket authentication [Y/n] [PRESS ENTER]
Enabled successfully!
Reloading privilege tables..
... Success!
You already have your root account protected, so you can safely answer 'n'.
Change the root password? [Y/n] [ANSWER n]
... skipping.
By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them. This is intended only for testing, and to make the installation
go a bit smoother. You should remove them before moving into a
production environment.
Remove anonymous users? [Y/n] [PRESS ENTER]
... Success!
Normally, root should only be allowed to connect from 'localhost'. This
ensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] [PRESS ENTER]
... Success!
By default, MariaDB comes with a database named 'test' that anyone can
access. This is also intended only for testing, and should be removed
before moving into a production environment.
Remove test database and access to it? [Y/n] [PRESS ENTER]
\- Dropping test database...
... Success!
\- Removing privileges on test database...
... Success!
Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.
Reload privilege tables now? [Y/n] [PRESS ENTER]
... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDB
installation should now be secure.
Thanks for using MariaDB!
MariaDB의 SQL 셸에 로그인합니다.
$ sudo mysql
프롬프트가 표시되면 루트 비밀번호를 입력합니다.
접근 권한이 있는 테스트 데이터베이스와 사용자를 생성합니다. database 및 user를 원하는 것으로 바꾸고, password는 강력한 비밀번호로 바꿉니다.
CREATE DATABASE testdb;
CREATE USER 'user' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON testdb.* TO 'user';
MySQL 셸을 종료합니다.
exit
6단계 - Caddy 구성
Caddy는 API 호출, JSON 파일 또는 Caddyfile을 통해 여러 가지 방법으로 구성할 수 있습니다. Caddyfile은 Caddy를 구성하는 가장 쉬운 방법으로, 이 튜토리얼에서 사용할 것입니다.
Caddy를 구성하기 전에 사이트의 루트 디렉토리를 생성해야 합니다.
$ sudo mkdir -p /var/www/example.com/html
-p 플래그는 누락된 부모 디렉토리를 생성합니다.
Caddy의 로그 파일을 저장할 디렉토리도 생성해야 합니다.
$ sudo mkdir /var/log/caddy
Caddy 서버는 설치 시 작업을 처리하는 caddy 사용자를 생성합니다. Caddy가 로그 디렉토리에 접근하고 쓸 수 있도록 권한을 부여해야 합니다.
$ sudo chown -R caddy:caddy /var/log/caddy
설치 중에 Caddy는 /etc/caddy/Caddyfile에 기본 Caddyfile을 생성했습니다. 열어봅니다.
$ sudo nano /etc/caddy/Caddyfile
다음과 비슷하게 보일 것입니다.
# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace the line below with your
# domain name.
:80
# Set this path to your site's directory.
root * /usr/share/caddy
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile
:80는 Caddy가 포트 번호 80을 통해 모든 것을 제공하도록 지시합니다. root는 사이트의 홈 디렉토리 경로를 설정합니다. file_server는 Caddy가 정적 파일 서버로 실행되도록 합니다.
위 코드를 다음 코드로 바꿉니다.
{
experimental_http3
}
example.com {
root * /var/www/example.com/html
log {
output file /var/log/caddy/example.com.access.log {
roll_size 3MiB
roll_keep 5
roll_keep_for 48h
}
format console
}
encode gzip zstd
php_fastcgi unix//run/php/php7.4-fpm.sock
tls [email protected] {
протоколы tls1.2 tls1.3
}
}
Caddyfile의 모든 섹션을 살펴보겠습니다.
- Caddyfile의 첫 번째 블록은 호스트 이름을 지정하지 않는 한 전역 블록입니다. 전역 블록은 서버에서 호스팅하는 모든 사이트에 적용되는 지시문을 포함합니다. 예제에서는 실험적인 HTTP/3 프로토콜에 대한 지원을 활성화했습니다. 전역 블록은 완전히 선택 사항이며 Caddyfile을 사이트 블록으로 직접 시작할 수 있습니다.
- 다음 블록은 사이트 블록입니다. 서버에 사이트가 하나만 있는 경우 구성 블록으로 묶을 필요가 없지만 여러 사이트를 호스팅할 경우 각 사이트의 구성을 자체 블록에 호스팅해야 합니다. 사이트 블록은 중괄호로 표시됩니다. 모든 사이트 블록은 사이트의 호스트 이름으로 시작합니다.
log는 HTTP 요청 로깅을 활성화하고 구성합니다.log지시문이 없으면 Caddy는 아무것도 기록하지 않습니다.output은 로그 파일을 쓸 위치를 구성합니다.format은 로그를 인코딩하거나 형식을 지정하는 방법을 설명합니다.console은 로그 항목을 사람이 읽을 수 있도록 형식을 지정합니다.encode지시문은 사이트에 대한 Gzip 및 Zstandard 압축을 활성화합니다.php_fastcgi는 요청을 PHP FastCGI 서버(예:php-fpm)로 프록시합니다. 여기서는 Unix 소켓을 통해 요청을 수신하고 있습니다.tls블록은 SSL 인증서 및 보안과 관련된 설정을 구성합니다. 여기서는 TLSv1.2 및 TLSv1.3 프로토콜에 대한 지원을 활성화했습니다. 기본적으로 Caddy는 기본적으로 TLS v1.2를 지원합니다. Caddy는 모든 사이트에 대해 SSL 인증서를 자동으로 생성합니다. Caddy가 SSL을 생성하지 않도록 하려면 호스트 이름 대신 IP 주소를 사용하거나 전체 URL(예: http://example.com)을 지정하면 됩니다. 이러한 경우 Caddy는 SSL 인증서를 생성하지 않습니다.
지금까지 Caddyfile 작성의 기본 사항을 다루었으며, 이를 통해 시작할 수 있습니다. 공식 문서에서 더 많은 내용을 읽을 수 있습니다.
7단계 - PHP 구성
이제 Caddyfile이 준비되었으므로 PHP를 구성할 시간입니다.
먼저 PHP 프로세스의 사용자 이름을 변경해야 합니다. /etc/php-fpm.d/www.conf 파일을 엽니다.
$ sudo nano /etc/php/7.4/fpm/pool.d/www.conf
파일에서 user=www-data 및 group=www-data 줄을 찾아 caddy로 변경합니다.
...
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
; RPM: apache user chosen to provide access to the same directories as httpd
user = caddy
; RPM: Keep a group allowed to write in log dir.
group = caddy
...
또한 파일에서 listen.owner=www-data 및 listen.group=www-data 줄을 찾아 caddy로 변경합니다.
listen.owner = caddy
listen.group = caddy
Ctrl+X를 눌러 파일을 저장하고, 프롬프트가 표시되면 Y를 입력합니다.
PHP-fpm 프로세스를 재시작합니다.
$ sudo systemctl restart php7.4-fpm
8단계 - 데모 사이트 시작
이제 Caddyfile을 만들고 PHP를 서버와 함께 실행하도록 구성했으므로 데모 웹사이트를 만들고 시작할 시간입니다.
도메인 이름이 서버의 IP 주소를 가리키고 있는지 확인합니다.
위에서 만든 Caddyfile의 변경 사항을 적용하기 위해 Caddy 서버를 재시작합니다.
$ sudo systemctl restart caddy
Caddy 서버의 상태를 확인하여 제대로 작동하는지 확인합니다.
$ sudo systemctl status caddy
? caddy.service - Caddy
Loaded: loaded (/lib/systemd/system/caddy.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2020-05-20 07:09:25 UTC; 2s ago
Docs: https://caddyserver.com/docs/
Main PID: 25410 (caddy)
Tasks: 7 (limit: 1074)
Memory: 17.8M
CGroup: /system.slice/caddy.service
??25410 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
May 20 07:09:25 example.com caddy[25410]: 2020/05/20 07:09:25 [INFO][example.com] Obtain: Lock acquired; proceeding...
May 20 07:09:25 example.com caddy[25410]: 2020/05/20 07:09:25 [INFO][cache:0xc0006f8cd0] Started certificate maintenance routine
May 20 07:09:25 example.com caddy[25410]: 2020/05/20 07:09:25 [INFO] acme: Registering account for [email protected]
May 20 07:09:26 example.com caddy[25410]: 2020/05/20 07:09:26 [INFO][example.com] Waiting on rate limiter...
May 20 07:09:26 example.com caddy[25410]: 2020/05/20 07:09:26 [INFO][example.com] Done waiting
May 20 07:09:26 example.com caddy[25410]: 2020/05/20 07:09:26 [INFO] [example.com] acme: Obtaining bundled SAN certificate given a CSR
May 20 07:09:27 example.com caddy[25410]: 2020/05/20 07:09:27 [INFO] [example.com] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/4696123289
May 20 07:09:27 example.com caddy[25410]: 2020/05/27 07:09:27 [INFO] [example.com] acme: use tls-alpn-01 solver
May 20 07:09:27 example.com caddy[25410]: 2020/05/20 07:09:27 [INFO] [example.com] acme: Trying to solve TLS-ALPN-01
May 20 07:09:27 example.com caddy[25410]: 2020/05/20 07:09:27 http: TLS handshake error from 127.0.0.1:39466: EOF
위에서 볼 수 있듯이 Caddy는 Caddyfile을 생성한 후 서버를 처음 재시작할 때 인증서를 자동으로 생성했습니다.
Caddy가 PHP를 렌더링하고 MariaDB 데이터베이스에 연결할 수 있는지 확인하기 위해 테스트 페이지를 생성합시다.
$ sudo nano /var/www/example.com/html/test.php
편집기에 다음 코드를 붙여넣습니다. 이전에 생성한 MariaDB 자격 증명으로 `
새 게시물을 받은 편지함에서 받기
스팸은 없습니다. 언제든지 구독 해지 가능합니다.