---
# System prepended metadata

title: EC2 安裝 brotli
tags: [AWS]

---

###### tags: `AWS`
# EC2 安裝 brotli

## Apache

mod 原始碼
https://github.com/kjdev/apache-mod-brotli

需安裝 libtool, httpd-devel
``` 
$ yum install libtool http-devel 
```

 然後照 github 上的指令編譯模組
 ```
 $ git clone --depth=1 --recursive https://github.com/kjdev/apache-mod-brotli.git
$ cd apache-mod-brotli
$ ./autogen.sh
$ ./configure
$ make
```
編譯完成後，安裝到 httpd 模組的路徑下：
```
$ install -p -m 755 -D .libs/mod_brotli.so /etc/httpd/modules/mod_brotli.so
 ```
 
然後在 /etc/httpd/conf.d/ 目錄下新增 brotli 的設定檔，內容如下：
 
```conf=
 # Load module
LoadModule brotli_module modules/mod_brotli.so

<IfModule brotli_module>
  # Output filter
  AddOutputFilterByType BROTLI text/html text/plain text/css text/xml text/javascript application/javascript

  # SetOutputFilter BROTLI
  # SetEnvIfNoCase Request_URI \.txt$ no-br

  # Compression
  ## BrotliCompressionLevel: 0-11 (default: 11)
  BrotliCompressionLevel 10

  ## BrotliWindowSize: 10-24 (default: 22)
  BrotliWindowSize 22

  # Specifies how to change the ETag header when the response is compressed
  ## BrotliAlterEtag: AddSuffix, NoChange, Remove (default: AddSuffix)
  BrotliAlterEtag AddSuffix

  # Filter note
  BrotliFilterNote Input  brotli_in
  BrotliFilterNote Output brotli_out
  BrotliFilterNote Ratio  brotli_ratio

  LogFormat '"%r" %{brotli_out}n/%{brotli_in}n (%{brotli_ratio}n)' brotli
  CustomLog logs/access_log brotli
</IfModule>
 ```
 
如果是複製 github 上的範例，javascript 壓縮並沒有開啟，需自行加入。

重新啟動 httpd 服務。如果原先有啟用 gzip 壓縮，需先取消 gzip。

在瀏覽器檢查相關檔案是否已經變成 br 壓縮。

![](https://i.imgur.com/rTBEHo3.png)


## Nginx
參考這篇文章：
https://www.majlovesreg.one/adding-brotli-to-a-built-nginx-instance

儲存指令檔 mkbrotli，內容如下
```shell=
#!/bin/bash

# https://www.majlovesreg.one/tag/code/
# https://www.majlovesreg.one/adding-brotli-to-a-built-nginx-instance
# https://github.com/majal/maj-server/tree/master/nginx-modules-brotli

# Install needed development packages if not yet installed in the system
# sudo apt -y install git libpcre3 libpcre3-dev zlib1g zlib1g-dev openssl libssl-dev

# For predefined NGINX version, use:
# ngver=1.17.1

# For passing the version via the command line (i.e.: user@server:~$ ./mkbrotli 1.17.1), use:
ngver=$1

# For automated detection of currently installed NGINX version (not to be used for auto-updating, see hooks in post), use:
# ngver=$(nginx -v 2>&1 | grep -o '[0-9\.]*')

[ "${ngver}" ] || { echo "Please supply NGINX version. Exiting..."; exit 7; }

# Get configure parameters of installed NGINX. Not needed if NGINX was configured '--with-compat'.
# Uncomment one of the lines below if the script sucessfully builds modules but NGINX throws a "not binary compatible" error.
# confparams=$(nginx -V 2>&1 | grep -o -- '--prefix='.*)
# confparams=$(nginx -V 2>&1 | grep -o -- '--[^with]'.*)
# confparams=$(nginx -V 2>&1 | grep -- '--' | sed "s/.*' //")
# confparams=$(nginx -V 2>&1 | grep -o -- "--prefix='.*'$")

# To automatically select NGINX modules directory:
[ -d /usr/share/nginx/modules ] && moddir=/usr/share/nginx/modules
[ -d $(nginx -V 2>&1 | grep -o 'prefix=[^ ]*' | sed 's/prefix=//')/modules ] && moddir="$(nginx -V 2>&1 | grep -o 'prefix=[^ ]*' | sed 's/prefix=//')/modules"
[ -d $(nginx -V 2>&1 | grep -o 'modules-path=[^ ]*' | sed 's/modules-path=//') ] && moddir="$(nginx -V 2>&1 | grep -o 'modules-path=[^ ]*' | sed 's/modules-path=//')"

# To manually set NGINX modules directory:
# moddir=/path/to/modules/directory
[ "${moddir}" ] || { echo '!! missing modules directory, exiting...'; exit 1; }

# Set temporary directory and build on it
builddir="$(mktemp -d)"
cd "${builddir}"

echo
echo '################################################################################'
echo
echo "Building Brotli for NGINX ${ngver}"
echo "Temporary build directory: ${builddir}"
echo "Modules directory: ${moddir}"
echo

# Download and unpack NGINX
wget https://nginx.org/download/nginx-${ngver}.tar.gz && { tar zxf nginx-${ngver}.tar.gz && rm nginx-${ngver}.tar.gz; } || { echo '!! download failed, exiting...'; exit 2; }

# Download, initialize, and make Brotli dynamic modules
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli && git submodule update --init && cd ../nginx-${ngver}
[ "${confparams}" ] && nice -n 19 ionice -c 3 "./configure --add-dynamic-module=../ngx_brotli ${confparams}" || nice -n 19 ionice -c 3 ./configure --with-compat --add-dynamic-module=../ngx_brotli
nice -n 19 ionice -c 3 make modules || { echo '!! configure or make failed, exiting...'; exit 4; }

# Replace Brotli in modules directory
[ -f "${moddir}/ngx_http_brotli_filter_module.so" ] && sudo mv "${moddir}/ngx_http_brotli_filter_module.so" "${moddir}/ngx_http_brotli_filter_module.so.old"
[ -f "${moddir}/ngx_http_brotli_static_module.so" ] && sudo mv "${moddir}/ngx_http_brotli_static_module.so" "${moddir}/ngx_http_brotli_static_module.so.old"
sudo cp objs/*.so "${moddir}/"
sudo chmod 644 "${moddir}/ngx_http_brotli_filter_module.so" || { echo '!! module permissions failed, exiting...'; exit 5; }
sudo chmod 644 "${moddir}/ngx_http_brotli_static_module.so" || { echo '!! module permissions failed, exiting...'; exit 6; }

# Clean up build files
cd "${builddir}/.."
sudo rm -r "${builddir}/ngx_brotli"
rm -r "${builddir}"

echo
echo "Sucessfully built and installed latest Brotli for NGINX ${ngver}"
echo "Modules can be found in ${moddir}"
echo "Next step: Configure dynamic modules and reload/restart NGINX."
echo
echo '################################################################################'
echo

# Start/restart NGINX.
# Not recommended if script is hooked since NGINX is automatically restarted by the package manager (e.g. apt) after an upgrade.
# Restarting NGINX before the upgrade could cause a module version mismatch.
# sudo nginx -t && { systemctl is-active nginx && sudo systemctl restart nginx || sudo systemctl start nginx; } || true
# echo
# systemctl --no-pager status nginx
# echo
```
將指令檔加上可執行的屬性

```
$ chmod u+r mkbrotli
```

安裝 pcre-devel 及 zlib-devel
```shell
$ yum install pcre-devel zlib-devel
```

查詢 nginx 的版本
```
$ nginx -v
nginx version: nginx/1.20.0
```

執行 mkbrotli 並附上 nginx 版本號碼
```
$ mkbrotli 1.20.0
```

接下來會編譯出 ngx_http_brotli_filter_module.so 及 ngx_http_brotli_static_module.so，放在 /usr/lib64/nginx/modules 下。

在 /usr/share/nginx/modules 建立 module_brotli.conf 檔，內容如下：
```
load_module modules/ngx_http_brotli_filter_module.so;
load_module modules/ngx_http_brotli_static_module.so;
```

將 /usr/lib64/nginx/modules 下的兩個 .so 檔移到 /usr/share/nginx/modules

```
$ mv /usr/lib64/nginx/modules/ngx_http* /usr/share/nginx/modules
```

在 /etc/nginx/conf.d 建立 brotli.conf，內容如下：
```shell=
brotli on;
brotli_static on;
brotli_comp_level 6;
brotli_types text/plain text/css text/javascript application/javascript application/json image/svg+xml;
```

brotli_comp_level 會影響壓縮比及壓縮速度。1 為最小壓縮比也最快。11 為最大壓縮比，但也最耗時。實務上可自行測試找出對該網站對適合的參數 


重新啟動 nginx。檢查網頁中的檔案是否正確壓縮。

![](https://i.imgur.com/ZomQbO3.png)


