🧟

FrankenPHP を Debian 12 bookworm にインストール

2024/05/05に公開

FrankenPHP 公式サイトのスクリーンショット

この記事はインフラ初心者が纏めているため、あまり信用しないでください。この記事を参考にセットアップしたことによって被った損害・損失に対し、いかなる場合でも一切の責任を負いませんのでご了承ください。あくまでも自己責任でお願いします🙇‍♂️

本記事では、Debian のインストールと設定は完了しているものとする。最終的に目指す構成は以下の通り。

  • OS: Debian 12 bookworm
  • web サーバー + PHP: FrankenPHP (Caddy + PHP8.3) - 本記事
  • データベース: MariaDB

ファイアウォールの設定

80番ポートと443番ポートを開放する。

$ ufw limit 'WWW Full' && sudo ufw reload && sudo ufw status
Rule added
Rule added (v6)
Status: active

To                         Action      From
--                         ------      ----
SSH                        LIMIT       Anywhere
WWW Full                   LIMIT       Anywhere
SSH (v6)                   LIMIT       Anywhere (v6)
WWW Full (v6)              LIMIT       Anywhere (v6)

ステータスが active で、WWW Full がリストにあれば完了。

一度追加したルールを削除する

追加した削除したルールを削除する場合は、以下のコマンドを実行する。

$ sudo ufw delete limit SSH && sudo ufw reload

個別に削除する場合は

$ ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] SSH                        LIMIT IN    Anywhere
[ 2] SSH (v6)                   LIMIT IN    Anywhere (v6)

上記で表示された番号を指定する。

$ ufw delete 2 && sudo ufw reload

FrankenPHP をインストール

一般的に web サイト公開環境といえば、Nginx + PHP-FPM が多いと思います。しかし、環境構築とメンテナンスのハードルが高いので、FrankenPHP に期待している。

インストールする場所へ Path を通す

/usr/local/sbin への Path を通す。

$ vi ~/.bashrc

下記を追記。

+ export PATH=/usr/local/sbin:$PATH

変更内容を反映させる。

$ source ~/.bashrc

バイナリーを Github からダウンロードして配置

$ wget https://github.com/dunglas/frankenphp/releases/download/v1.2.2/frankenphp-linux-x86_64 && \
sudo mv ~/frankenphp-linux-x86_64 /usr/local/sbin/frankenphp && \
sudo chmod +x /usr/local/sbin/frankenphp && \
/usr/local/sbin/frankenphp -v

FrankenPHP の設定

ここからの作業は Nginx や Apache と同じような一般的な作業。

ユーザーの設定を変更

FrankenPHP 用のユーザーを作成し www-data グループに所属させる。
※ 下記の例では作業用ユーザー debian も一緒に www-data グループに所属させている。

$ sudo useradd -mU -s /usr/sbin/nologin -d /opt/caddy caddy && \
sudo usermod -aG www-data caddy && \
sudo usermod -aG www-data debian

公開ディレクトリを作成

web サイト公開ディレクトリの権限を変更し、www-data グループに所属していれば追加・更新・削除を行えるようにする。

$ sudo mkdir /var/www && \
sudo chown -R caddy:www-data /var/www && \
sudo chmod -R 2775 /var/www && \
sudo find /var/www -type d -exec sudo chmod 2775 {} \; && \
sudo find /var/www -type f -exec sudo chmod 2664 {} \; && \
exit

サーバーからログアウトしているはずなので、再度ログインする。

Caddyfile を設定

FrankenPHP の web サーバーは Go 言語で書かれた Caddy が使用されている。設定ファイルの書き方は Caddy と同じ。

$ sudo vi /etc/caddy/Caddyfile

(encode) {
    encode zstd br gzip
    php_server
}

(header-cache-control) {
    @static {
        file
        path *.css *.js *.jpeg *.jpg *.png *.gif *.webp *.avif *.svg *.eot *.ttf *.woff *.woff2
    }

    header @static Cache-Control "public, max-age=691200"
}

(header-security) {
    header Referrer-Policy no-referrer-when-downgrade
    header X-Content-Type-Options nosniff
    header X-Download-Options noopen
    header X-Frame-Options SAMEORIGIN
    header X-XSS-Protection "1; mode=block"
}

(header-cors) {
    @origin header Origin {args[0]}
    header @origin Access-Control-Allow-Origin "{args[0]}"
    header @origin Access-Control-Allow-Methods "GET,POST,PUT,DELETE,OPTIONS"
}

(header-https) {
    header Content-Security-Policy "default-src https: data: 'unsafe-eval' 'unsafe-inline';"
    header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    header X-SSL-Status https
}

(createlog) {
    log {
        hostnames {args[0]}
        output file /opt/caddy/log/access-{args[0]}.log {
            roll_size 1gb
            roll_keep 5
            roll_keep_for 7d
        }
        output file /opt/caddy/log/error-{args[0]}.log {
            level ERROR
            roll_size 1gb
            roll_keep 5
            roll_keep_for 7d
        }
    }
}

{
    frankenphp
    order php_server before file_server
    http_port  80
    https_port 443
    auto_https disable_redirects
}

http:// {
    root * /var/www/exmaple.com/public
    import header-cache-control
    import header-security
    import header-cors 192.168.10.20
    import encode
}

exmaple.com:80,
exmaple.com:443 {
    redir https://www.exmaple.com{uri} permanent
    import header-cache-control
    import header-security
    import header-cors exmaple.com
    import encode
}

www.exmaple.com:80,
www.exmaple.com:443 {
    root * /var/www/exmaple.com/public
    import header-cache-control
    import header-security
    import header-cors www.exmaple.com
    import header-https
    import encode
    import createlog www.exmaple.com
}

FrankenPHP をサービスに登録

$ sudo vi /etc/systemd/system/frankenphp.service

以下をペースト。

# frankenphp.service
#
# For using Caddy with a config file.
#
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
#
# See https://caddyserver.com/docs/install for instructions.
#
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.

[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target

[Service]
Type=notify
User=caddy
Group=www-data
ExecStart=/usr/local/sbin/frankenphp run --environ --config /etc/caddy/Caddyfile
ExecReload=/bin/kill -USR1 $MAINPID
ExecStop=/usr/local/sbin/frankenphp stop
Restart=on-failure
RestartSec=5s
TimeoutStopSec=5s
LimitNOFILE=65536
LimitNPROC=64
PrivateTmp=true
PrivateDevices=true
ProtectSystem=full
ReadWriteDirectories=/opt/caddy
Environment=CADDYPATH=/opt/caddy
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE

[Install]
WantedBy=multi-user.target

FrankenPHP をサービスに登録。

$ sudo systemctl enable frankenphp && \
sudo systemctl start frankenphp && \
sudo systemctl status frankenphp

これで web サイトが公開されているはず。

PHP.ini を作成

自身で FrankenPHP のバイナリをビルドした場合を除き、php.ini の設置場所は /lib 以下になっている。FrankenPHP 側で php.ini は準備されていないから自前で用意。

$ sudo vi /lib/php.ini

/run/mysqld/mysqld.sock の箇所は環境に合わせて変更。
MariaDB の場合は /etc/mysql/mariadb.cnf で確認できる。

[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
implicit_flush = Off
serialize_precision = -1
zend.enable_gc = On
expose_php = Off
max_execution_time = 30
max_input_time = 60
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_log = /var/log/php_errors.log
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = On
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
html_errors = Off
request_order = "GP"
auto_globals_jit = On
post_max_size = 4M
upload_max_filesize = 4M
max_file_uploads = 20
default_mimetype = "text/html"
file_uploads = On
allow_url_fopen = Off
default_socket_timeout = 60
open_basedir = /var/www

[Date]
date.timezone = "Asia/Tokyo"

[mbstring]
mbstring.language = Japanese
mbstring.detect_order = ASCII,ISO-2022-JP,UTF-8,eucJP-win,SJIS-win
mbstring.encoding_translation = Off
mbstring.substitute_character = none
mbstring.func_overload = 0

[mail function]
SMTP = localhost
smtp_port = 25
sendmail_path = /usr/sbin/sendmail -t -i
mail.add_x_header = On

[Session]
session.save_handler = files
session.save_path = "/tmp/php/session"
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5

[Pdo_mysql]
pdo_mysql.default_socket = /run/mysqld/mysqld.sock

[MySQLi]
mysqli.default_socket = /run/mysqld/mysqld.sock

[OPcache]
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8M
opcache.max_accelerated_files=4000
opcache.revalidate_freq=0
opcache.fast_shutdown=1

[apcu]
apc.enabled=1
apc.enable_cli=1
apc.shm_size=64M
apc.ttl=3600
apc.gc_ttl=3600
apc.user_ttl=7200
apc.cache_by_default=1
apc.filters=.*\.php
apc.stat=1
apc.serializer=php
apc.use_request_time=1
apc.include_once_override=0

[Memcached]
;extension=memcached.so

関連記事

Discussion