Verification: a143cc29221c9be0

Nginx отдает php файлы на скачивание

Nginx отдает php файлы на скачивание

Требования


  • Сервер-контейнер (LXC или LXD), виртуальная машина, или обычный железный сервер, с не менее чем 512Мб оперативной памяти и установленной Ubuntu 18.04 или более свежей.
  • Доступные из интернета порты 80 и 443
  • Доменное имя, связанное с публичным ip-адресом этого сервера
  • Доступ с правами root (sudo).

Обзор архитектуры

Архитектура такая же, как было описано ранее, трехуровневое web-приложение. Оно состоит из скриптов PHP, исполняемых на обработчике PHP, и статических файлов, обрабатываемых веб-сервером.


Общие принципы


  • Многие команды для настройки в скрипте обернуты в условия (if) для идемпотентности: скрипт можно запускать несколько раз без риска изменения настроек, которые уже готовы.
  • Скрипт старается устанавливать ПО из репозиториев, так что вы можете применять обновления системы в одну команду (apt upgrade для Ubuntu).
  • Команды стараются определить, что они запускаются в контейнере, чтобы изменить соответствующим образом свои настройки.
  • Для того, чтобы задать число запускаемых процессов\потоков в настройках, скрипт пробует угадать автоматические параметры настройки для работы в контейнерах, виртуальных машинах, «железных» серверах.
  • При описании настроек всегда думаем в первую очередь об автоматизации, которая, как мы надеемся, станет основой для создания вашей собственной инфраструктуры как кода.
  • Все команды запускаются от пользователя root, потому что они изменяют основные системные настройки, но непосредственно WordPress работает от обычного пользователя.

Установка переменных окружения

Установите следующие переменные окружения, прежде чем запускать скрипт:


  • WORDPRESS_DB_PASSWORD — пароль к базе данных WordPress
  • WORDPRESS_ADMIN_USER — имя администратора WordPress
  • WORDPRESS_ADMIN_PASSWORD — пароль администратора WordPress
  • WORDPRESS_ADMIN_EMAIL — email администратора WordPress
  • WORDPRESS_URL — полный URL сайта WordPress, начиная с https://.
  • LETS_ENCRYPT_STAGING — пустая по-умолчанию, но, выставив значение в 1, вы будете использовать staging сервера Let’s Encrypt, необходимые для частого запроса сертификатов при тестировании ваших настроек, иначе Let’s Encrypt может временно заблокировать ваш ip-адрес из-за большого числа запросов.

Скрипт проверяет, что эти связанные с WordPress переменные выставлены, и завершает работу, если нет.
Строки скрипта 572-576 проверяют значение LETS_ENCRYPT_STAGING.


Установка производных переменных окружения

Скрипт в строках 55-61 выставляет следующие переменные окружения, либо в некоторое жестко заданное значение, либо с применением значения, полученного из переменных, установленных в предыдущем разделе:


  • DEBIAN_FRONTEND="noninteractive" — сообщает приложениям, что они запускаются в скрипте и нет возможности взаимодействия с пользователем.
  • WORDPRESS_CLI_VERSION="2.4.0" — версия приложения WordPress CLI.
  • WORDPRESS_CLI_MD5= "dedd5a662b80cda66e9e25d44c23b25c" — контрольная сумма исполняемого файла WordPress CLI 2.4.0 (версия указывается в переменной WORDPRESS_CLI_VERSION). Скрипт на 162 строке использует это значение для проверки, что был скачан корректный файл WordPress CLI.
  • UPLOAD_MAX_FILESIZE="16M" — максимальный размер файла, который может быть закачан в WordPress. Эта настройка используется в нескольких местах, так что проще задавать ее в одном месте.
  • TLS_HOSTNAME= "$(echo ${WORDPRESS_URL} | cut -d'/' -f3)" — hostname системы, извлекаемый из переменной WORDPRESS_URL. Используется для получения соответствующих TLS/SSL сертификатов от Let’s Encrypt, а также для внутренней проверки WordPress.
  • NGINX_CONF_DIR="/etc/nginx" — путь к каталогу с настройками NGINX, включая основной файл nginx.conf.
  • CERT_DIR="/etc/letsencrypt/live/${TLS_HOSTNAME}" — путь к сертификатам Let’s Encrypt для сайта WordPress, получаемый из переменной TLS_HOSTNAME.

Назначение hostname WordPress серверу

Скрипт устанавливает hostname серверу, чтобы значение соответствовало доменному имени сайта. Это не обязательно, но так удобнее отправлять исходящую почту через SMTP при настройке единственного сервера, как это настраивается скриптом.


код скрипта

# Change the hostname to be the same as the WordPress hostname
if [ ! "$(hostname)" == "${TLS_HOSTNAME}" ]; then
  echo " Changing hostname to ${TLS_HOSTNAME}"
  hostnamectl set-hostname "${TLS_HOSTNAME}"
fi

Добавление hostname в /etc/hosts

Дополнение WP‑Cron используется для запуска периодических задач, требует, чтобы WordPress мог получить доступ к самому себе через HTTP. Чтобы убедиться, что WP-Cron работает корректно на всех окружениях, скрипт добавляет строчку в файл /etc/hosts, так что WordPress может получить доступ к самому себе через интерфейс loopback:


код скрипта

# Add the hostname to /etc/hosts
if [ "$(grep -m1 "${TLS_HOSTNAME}" /etc/hosts)" = "" ]; then
  echo " Adding hostname ${TLS_HOSTNAME} to /etc/hosts so that WordPress can ping itself"
  printf "::1 %s\n127.0.0.1 %s\n" "${TLS_HOSTNAME}" "${TLS_HOSTNAME}" >> /etc/hosts
fi

Установка инструментов, требуемых для последующих шагов

Оставшаяся часть скрипта нуждается в некоторых программах и подразумевает, что репозитории актуальны. Мы обновляем список репозиториев, после чего устанавливаем нужные инструменты:


код скрипта

# Make sure tools needed for install are present
echo " Installing prerequisite tools"
apt-get -qq update
apt-get -qq install -y \
  bc \
  ca-certificates \
  coreutils \
  curl \
  gnupg2 \
  lsb-release

Добавление репозиториев NGINX Unit и NGINX

Скрипт устанавливает NGINX Unit и NGINX с открытым исходным кодом из официальных репозиториев NGINX, чтобы удостовериться, что используются версии с последними обновлениями безопасности и исправлениями ошибок.

Скрипт добавляет репозиторий NGINX Unit, а затем — репозиторий NGINX, добавляя ключ репозиториев и файлы настроек apt, задающих доступ к репозиториям через интернет.

Реальная установка NGINX Unit и NGINX происходит в следующем разделе. Мы предварительно добавляем репозитории, чтобы не обновлять метаданные несколько раз, что делает установку быстрее.


код скрипта

# Install the NGINX Unit repository
if [ ! -f /etc/apt/sources.list.d/unit.list ]; then
  echo " Installing NGINX Unit repository"
  curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
  echo "deb https://packages.nginx.org/unit/ubuntu/ $(lsb_release -cs) unit" > /etc/apt/sources.list.d/unit.list
fi

# Install the NGINX repository
if [ ! -f /etc/apt/sources.list.d/nginx.list ]; then
  echo " Installing NGINX repository"
  curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -
  echo "deb https://nginx.org/packages/mainline/ubuntu $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx.list
fi

Установка NGINX, NGINX Unit, PHP MariaDB, Certbot (Let’s Encrypt) и их зависимостей

Как только все репозитории добавлены, обновляем метаданные и устанавливаем приложения. Пакеты, устанавливаемые скриптом, также включают расширения PHP, рекомендуемые при запуске WordPress.org


код скрипта

echo " Updating repository metadata"
apt-get -qq update

# Install PHP with dependencies and NGINX Unit
echo " Installing PHP, NGINX Unit, NGINX, Certbot, and MariaDB"
apt-get -qq install -y --no-install-recommends \
  certbot \
  python3-certbot-nginx \
  php-cli \
  php-common \
  php-bcmath \
  php-curl \
  php-gd \
  php-imagick \
  php-mbstring \
  php-mysql \
  php-opcache \
  php-xml \
  php-zip \
  ghostscript \
  nginx \
  unit \
  unit-php \
  mariadb-server

Настройка PHP для использования с NGINX Unit и WordPress

Скрипт создает файл настроек в каталоге conf.d. Тут задается максимальный размер загружаемых файлов для PHP, включается вывод ошибок PHP в STDERR, так что они будут записаны в журнал NGINX Unit, а также перезапускается NGINX Unit.


код скрипта

# Find the major and minor PHP version so that we can write to its conf.d directory
PHP_MAJOR_MINOR_VERSION="$(php -v | head -n1 | cut -d' ' -f2 | cut -d'.' -f1,2)"

if [ ! -f "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" ]; then
  echo " Configuring PHP for use with NGINX Unit and WordPress"
  # Add PHP configuration overrides
  cat > "/etc/php/${PHP_MAJOR_MINOR_VERSION}/embed/conf.d/30-wordpress-overrides.ini" 

Задание настроек базы данных MariaDB для WordPress

Мы выбрали MariaDB вместо MySQL, поскольку у нее больше активность сообщества, кроме того, она, возможно, предоставляет более высокую производительность по умолчанию (вероятно, тут все проще: чтобы поставить MySQL, надо добавить еще один репозиторий, прим. переводчика).

Скрипт создает новую базу данных и создает учетные данные для доступа WordPress через интерфейс loopback:


код скрипта

# Set up the WordPress database
echo " Configuring MariaDB for WordPress"
mysqladmin create wordpress || echo "Ignoring above error because database may already exist"
mysql -e "GRANT ALL PRIVILEGES ON wordpress.* TO \"wordpress\"@\"localhost\" IDENTIFIED BY \"$WORDPRESS_DB_PASSWORD\"; FLUSH PRIVILEGES;"

Установка программы WordPress CLI

На этом шаге скрипт устанавливает программу WP-CLI. С его помощью можно установить и управлять настройками WordPress без необходимости ручной правки файлов, обновления базы или входа в панель управления. Также с его помощью можно установить темы и дополнения и выполнить обновление WordPress.


код скрипта

if [ ! -f /usr/local/bin/wp ]; then
  # Install the WordPress CLI
  echo " Installing the WordPress CLI tool"
  curl --retry 6 -Ls "https://github.com/wp-cli/wp-cli/releases/download/v${WORDPRESS_CLI_VERSION}/wp-cli-${WORDPRESS_CLI_VERSION}.phar" > /usr/local/bin/wp
  echo "$WORDPRESS_CLI_MD5 /usr/local/bin/wp" | md5sum -c -
  chmod +x /usr/local/bin/wp
fi

Установка и настройка WordPress

Скрипт устанавливает последнюю версию WordPress в каталог /var/www/wordpress, а также изменяет настройки:


  • Соединение с базой данных работает через unix domain socket вместо TCP на loopback, чтобы сократить трафик TCP.
  • WordPress добавляет префикс https:// к URL, если клиенты соединяются с NGINX по протоколу HTTPS, а также отправляет удаленный hostname (как это предоставляет NGINX) в PHP. Мы применяем кусочек кода, чтобы это настроить.
  • WordPress нужно HTTPS для входа
  • Структура URL по молчанию основывается на ресурсах
  • Выставляются правильные права на файловой системе для каталога WordPress.

код скрипта

if [ ! -d /var/www/wordpress ]; then
  # Create WordPress directories
  mkdir -p /var/www/wordpress
  chown -R www-data:www-data /var/www

  # Download WordPress using the WordPress CLI
  echo " Installing WordPress"
  su -s /bin/sh -c 'wp --path=/var/www/wordpress core download' www-data

  WP_CONFIG_CREATE_CMD="wp --path=/var/www/wordpress config create --extra-php --dbname=wordpress --dbuser=wordpress --dbhost=\"localhost:/var/run/mysqld/mysqld.sock\" --dbpass=\"${WORDPRESS_DB_PASSWORD}\""

  # This snippet is injected into the wp-config.php file when it is created;
  # it informs WordPress that we are behind a reverse proxy and as such
  # allows it to generate links using HTTPS
  cat > /tmp/wp_forwarded_for.php 

Настройка NGINX Unit

Скрипт настраивает NGINX Unit для запуска PHP и обработки путей WordPress, изолируя пространство имен процессов PHP и оптимизируя настройки производительности. Тут есть три функции, на которые стоит обратить внимание:


  • Поддержка пространств имен определяется по условию, основана на проверке запуска скрипта в контейнере. Это нужно, поскольку большинство настроек контейнеров не поддерживают вложенный запуск контейнеров.
  • Если есть поддержка пространств имен, отключается пространство имен network. Это нужно, чтобы позволить WordPress одновременно подключаться и к endpoints и быть доступным в интернете.
  • Максимальное число процессов определяется следующим образом: (Доступная память для запущенных MariaDB и NGINX Uniy)/(предел по оперативной памяти в PHP + 5)
    Это значение устанавливается в настройках NGINX Unit.

Также это значение подразумевает, что всегда есть как минимум два запущенных процесса PHP, что важно, поскольку WordPress делает много асинхронных запросов к самому себе, а без дополнительных процессов запуск, к примеру, WP-Cron, сломается. Вы, возможно, захотите увеличить или уменьшить эти ограничения, основываясь на ваших локальных настройках, потому что созданные настройки здесь — консервативные. На большинстве производственных систем настройки находятся между 10 и 100.


код скрипта

if [ "${container:-unknown}" != "lxc" ] && [ "$(grep -m1 -a container=lxc /proc/1/environ | tr -d '\0')" == "" ]; then
  NAMESPACES='"namespaces": {
        "cgroup": true,
        "credential": true,
        "mount": true,
        "network": false,
        "pid": true,
        "uname": true
    }'
else
  NAMESPACES='"namespaces": {}'
fi

PHP_MEM_LIMIT="$(grep 'memory_limit' /etc/php/7.4/embed/php.ini | tr -d ' ' | cut -f2 -d= | numfmt --from=iec)"
AVAIL_MEM="$(grep MemAvailable /proc/meminfo | tr -d ' kB' | cut -f2 -d: | numfmt --from-unit=K)"
MAX_PHP_PROCESSES="$(echo "${AVAIL_MEM}/${PHP_MEM_LIMIT}+5" | bc)"
echo " Calculated the maximum number of PHP processes as ${MAX_PHP_PROCESSES}. You may want to tune this value due to variations in your configuration. It is not unusual to see values between 10-100 in production configurations."

echo " Configuring NGINX Unit to use PHP and WordPress"
cat > /tmp/wordpress.json 

Настройка NGINX


Настройка основных параметров NGINX

Скрипт создает каталог для кэша NGINX, а затем создает основной файл настройки nginx.conf. Обратите внимание на число процессов-обработчиков и задание максимального размера файла для загрузки. Также есть строка, на которой подключается файл настройки сжатия, определяемый в следующем разделе, далее идут настройки кэширования.


код скрипта

# Make directory for NGINX cache
mkdir -p /var/cache/nginx/proxy

echo " Configuring NGINX"
cat > ${NGINX_CONF_DIR}/nginx.conf 

Настройка сжатия NGINX

Сжатие содержимого на лету перед отправкой его клиентам — отличный способ улучшения производительности сайта, но только если сжатие настроено правильно. Этот раздел скрипта основан на настройках отсюда.


код скрипта

cat > ${NGINX_CONF_DIR}/gzip_compression.conf 

Настройка NGINX для WordPress

Далее скрипт создает файл настройки для WordPress default.conf в каталоге conf.d. Здесь настраивается:


  • Активация сертификатов TLS, полученных от Let's Encrypt через Certbot (его настройка будет в следующем разделе)
  • Настройка параметров безопасности TLS, основанная на рекомендациях от Let's Encrypt
  • Подключение кэширования пропускаемых запросов на 1 час по умолчанию
  • Отключение журналирования доступа, а также журналирования ошибок, если файл не найден, для двух общих запрашиваемых файлов: favicon.ico и robots.txt
  • Запрет доступа к скрытым файлам и некоторым файлам .php, чтобы предотвратить нелегальный доступ или непреднамеренный запуск
  • Отключение журналирования доступа для статики и файлов шрифтов
  • Задание заголовка Access-Control-Allow-Origin для файлов шрифтов
  • Добавление маршрутизации для index.php и прочей статики.

код скрипта

cat > ${NGINX_CONF_DIR}/conf.d/default.conf 

Настройка Certbot для сертификатов от Let's Encrypt и их автоматическое продление

Certbot — бесплатный инструмент от Electronic Frontier Foundation (EFF), с помощью которого можно получать и автоматически обновлять сертификаты TLS от Let's Encrypt. Скрипт выполняет следующие действия, приводящие к настройке Certbot для обработки сертификатов от Let's Encrypt в NGINX:


  • Останавливает NGINX
  • Скачивает рекомендуемые параметры TLS
  • Запускает Certbot, чтобы получить сертификаты для сайта
  • Перезапускает NGINX для использования сертификатов
  • Настраивает ежедневный запуск Certbot в 3:24 ночи для проверки необходимости обновления сертификатов, а также, при необходимости, скачивания новых сертификатов и перезагрузки NGINX.

код скрипта

echo " Stopping NGINX in order to set up Let's Encrypt"
service nginx stop

mkdir -p /var/www/certbot
chown www-data:www-data /var/www/certbot
chmod g+s /var/www/certbot

if [ ! -f ${NGINX_CONF_DIR}/options-ssl-nginx.conf ]; then
  echo " Downloading recommended TLS parameters"
  curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:36:07 GMT" \
    -o "${NGINX_CONF_DIR}/options-ssl-nginx.conf" \
    "https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf" \
    || echo "Couldn't download latest options-ssl-nginx.conf"
fi

if [ ! -f ${NGINX_CONF_DIR}/ssl-dhparams.pem ]; then
  echo " Downloading recommended TLS DH parameters"
  curl --retry 6 -Ls -z "Tue, 14 Apr 2020 16:49:18 GMT" \
    -o "${NGINX_CONF_DIR}/ssl-dhparams.pem" \
    "https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem" \
    || echo "Couldn't download latest ssl-dhparams.pem"
fi

# If tls_certs_init.sh hasn't been run before, remove the self-signed certs
if [ ! -d "/etc/letsencrypt/accounts" ]; then
  echo " Removing self-signed certificates"
  rm -rf "${CERT_DIR}"
fi

if [ "" = "${LETS_ENCRYPT_STAGING:-}" ] || [ "0" = "${LETS_ENCRYPT_STAGING}" ]; then
  CERTBOT_STAGING_FLAG=""
else
  CERTBOT_STAGING_FLAG="--staging"
fi

if [ ! -f "${CERT_DIR}/fullchain.pem" ]; then
  echo " Generating certificates with Let's Encrypt"
  certbot certonly --standalone \
         -m "${WORDPRESS_ADMIN_EMAIL}" \
         ${CERTBOT_STAGING_FLAG} \
         --agree-tos --force-renewal --non-interactive \
         -d "${TLS_HOSTNAME}"
fi

echo " Starting NGINX in order to use new configuration"
service nginx start

# Write crontab for periodic Let's Encrypt cert renewal
if [ "$(crontab -l | grep -m1 'certbot renew')" == "" ]; then
  echo " Adding certbot to crontab for automatic Let's Encrypt renewal"
  (crontab -l 2>/dev/null; echo "24 3 * * * certbot renew --nginx --post-hook 'service nginx reload'") | crontab -
fi

Подготовка системы

Синхронизируем время.

Устанавливаем утилиту chrony:

apt-get install chrony

Выставляем нужный часовой пояс:

timedatectl set-timezone Europe/Moscow

* в данном примере московское время.

Разрешаем запуск демона chrony:

systemctl enable chrony

Настройка сервера баз данных

В качестве СУБД используем MariaDB.

Устанавливаем:

apt-get install mariadb-server

Разрешаем автозапуск и стартуем сервис:

systemctl enable mariadb

systemctl start mariadb

Задаем пароль для суперпользователя mysql:

mysqladmin -u root password

Подключаемся к MariaDB, создаем базу данных и пользователя:

mysql -uroot -p

> CREATE DATABASE nextcloud DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

> GRANT ALL PRIVILEGES ON nextcloud.* TO [email protected] IDENTIFIED BY ‘nextcloud’;

> \q

к содержанию ↑

Установка и настройка веб-сервера

PHP

Устанавливаем PHP, PHP-FPM и необходимые для работы nextcloud модули:

apt-get install php php-fpm php-common php-zip php-xml php-intl php-gd php-mysql php-mbstring php-curl php-imagick

Настраиваем php-fpm:

vi /etc/php/7.4/fpm/pool.d/www.conf

* путь к данной папке зависит от установленной версии php. В данном примере это 7.4.

Снимаем комментарии со следующей строки:

env[PATH] = /usr/local/bin:/usr/bin:/bin

Настраиваем php.ini:

vi /etc/php/7.4/fpm/php.ini

opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1

Разрешаем автозапуск php-fpm и перезапускаем его:

systemctl enable php7.4-fpm

systemctl restart php7.4-fpm

* php7.4-fpm зависит от версии установленного php.

к содержанию ↑

NGINX

Nextcloud можно развернуть на NGINX или Apache. В данной инструкции будем использовать первый.

Устанавливаем веб-сервер:

apt-get install nginx

Создаем виртуальный домен и настраиваем его для работы с облачным сервисом:

vi /etc/nginx/conf.d/nextcloud.conf

server {
        listen 80;
        server_name nextcloud.dmosk.ru;
        return 301 https://$server_name$request_uri;
}

server {
        listen 443 ssl;
        server_name nextcloud.dmosk.ru;

        ssl_certificate /etc/nginx/ssl/cert.pem;
        ssl_certificate_key /etc/nginx/ssl/cert.key;

        root /var/www/nextcloud;

        add_header Strict-Transport-Security “max-age=31536000; includeSubDomains” always;
        client_max_body_size 10G;
        fastcgi_buffers 64 4K;

        rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;
        rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;
        rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;

        index index.php;
        error_page 403 = /core/templates/403.php;
        error_page 404 = /core/templates/404.php;

        location = /robots.txt {
            allow all;
            log_not_found off;
            access_log off;
        }

        location ~ ^/(data|config|\.ht|db_structure\.xml|README) {
                deny all;
        }

        location ^~ /.well-known {
                location = /.well-known/carddav { return 301 /remote.php/dav/; }
                location = /.well-known/caldav  { return 301 /remote.php/dav/; }
                location ^~ /.well-known{ return 301 /index.php/$uri; }
                try_files $uri $uri/ =404;
        }

        location / {
                rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
                rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
                rewrite ^(/core/doc/[^\/]+/)$ $1/index.html;
                try_files $uri $uri/ index.php;
        }

        location ~ ^(.+?\.php)(/.*)?$ {
                try_files $1 = 404;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$1;
                fastcgi_param PATH_INFO $2;
                fastcgi_param HTTPS on;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }

        location ~* ^.+\.(jpg|jpeg|gif|bmp|ico|png|css|js|swf)$ {
                expires modified +30d;
                access_log off;
        }
}

* где:

  • nextcloud.dmosk.ru — домен, на котором будет работать сервис; 
  • /etc/nginx/ssl — каталог, в котором будут храниться сертификаты; 
  • /var/www/nextcloud — каталог с порталом.

Создаем каталог для хранения сертификатов и переходим в него:

mkdir /etc/nginx/ssl

cd /etc/nginx/ssl

Генерируем сертификат:

openssl req -new -x509 -days 1461 -nodes -out cert.pem -keyout cert.key -subj “/C=RU/ST=SPb/L=SPb/O=Global Security/OU=IT Department/CN=nextcloud.dmosk.ru/CN=nextcloud”

* данная команда создаст сертификат на 4 года для URL nextcloud.dmosk.ru или nextcloud.

После установки php мог установиться и запуститься apache. Отключаем его:

systemctl stop apache2

systemctl disable apache2

Проверяем конфигурацию nginx, завершаем его автозапуск и перезапускаем сервис:

nginx -t

systemctl enable nginx

systemctl restart nginx

к содержанию ↑

Установка Nextcloud

Устанавливаем пакет unzip:

apt-get install unzip

Заходим на страницу nextcloud и копируем ссылку на скачивание последней версии программы:

Ссылка для скачивания nextcloud

Переходим во временную папку и скачиваем исходник для установки, воспользовавшись скопированной ссылкой:

cd /tmp

wget https://download.nextcloud.com/server/releases/nextcloud-22.0.0.zip

* на момент обновления инструкции последняя версия была 22.

Распаковываем скачанный архив:

unzip nextcloud-*.zip

И переносим содержимое архива в каталог /var/www:

mv nextcloud /var/www

Задаем права доступа:

chown -R www-data:www-data /var/www/nextcloud

Открываем браузер и переходим по адресу https://nextcloud.dmosk.ru, где nextcloud.dmosk.ru — адрес облачного сервиса.

Задаем логин и пароль для администратора. В качестве базы данных выбираем MySQL/MariaDB (если предлагается выбор) и вводим в качестве логина, пароля и базы nextcloud.

Задаем параметры для подключения к базе данных

Завершаем установку.

Оптимизируем работу базы данных:

sudo -u www-data php /var/www/nextcloud/occ db:convert-filecache-bigint

к содержанию ↑

Тюнинг после установки

Для корректной работы системы выполним дополнительную настройку. После входа в nextcloud под администратором, переходим в настройки для пользователя:

Переходим в настройку Nextcloud

В разделе «Параметры сервера» переходим в Основные сведения:

Переходим к общим сведениям

В разделе «Проверка безопасности и параметров» мы можем увидеть список проблем:

В разделе «Проверка безопасности и параметров» мы можем увидеть список проблем

Рассмотрим процесс решения некоторых из них.

к содержанию ↑

1. Разрешённое максимальное значение использования памяти PHP ниже рекомендуемого значения в 512 МБ

Открываем на редактирование файл:

vi /etc/php/7.4/fpm/php.ini

Меняем настройку для memory_limit:

memory_limit = 512M

Перезапускаем php-fpm:

systemctl restart php7.4-fpm

2. В системе не установлены рекомендуемые модули PHP

Данная ошибка устраняется в зависимости от списка модулей, которых не хватает системе. Чаще всего, подходит команда:

dnf install php-

Например:

apt-get install php-gmp php-bcmath

После перезапускаем php-fpm:

systemctl restart php7.4-fpm

3. Не настроена система кеширования

Для решения проблемы мы должны установить и настроить одно из средств кэширования:

  • APCu
  • Redis
  • Memcached

Мы рассмотрим два последних варианта.

Redis

Устанавливаем сам Redis Server и модуль php:

apt-get install redis-server php-redis

* в случае установки сервера Redis на отдельный сервер, необходимо выполнить на сервере Nextcloud только установку php-redis.

Перезапускаем php-fpm:

systemctl restart php7.4-fpm

Открываем конфигурационный файл для nextcloud:

vi /var/www/nextcloud/config/config.php

И добавим:

  ‘memcache.local’ => ‘\\OC\\Memcache\\Redis’,
  ‘memcache.distributed’ => ‘\\OC\\Memcache\\Redis’,
  ‘memcache.locking’ => ‘\\OC\\Memcache\\Redis’,
  ‘redis’ => 
      array (
          ‘host’ => ‘localhost’,
          ‘port’ => 6379,
      ),

Готово.

Memcached

Выполняем установку модуля для php и сам сервис memcached:

apt-get install memcached php-memcached

После разрешаем его автозапуск:

systemctl enable memcached

Перезапускаем php-fpm:

systemctl restart php7.4-fpm

После этого открываем конфигурационный файл для nextcloud:

vi /var/www/nextcloud/config/config.php

И добавим:

  …
  ‘memcache.local’ => ‘\\OC\\Memcache\\Memcached’,
  ‘memcache.distributed’ => ‘\\OC\\Memcache\\Memcached’,
  ‘memcached_servers’ =>
  array (
    0 =>
    array (
      0 => ‘localhost’,
      1 => 11211,
    ),
  ),
  …

Готово.

к содержанию ↑

4. Не указан регион размещения этого сервера Nextcloud

Для решения проблемы открываем конфигурационный файл nextcloud:

vi /var/www/nextcloud/config/config.php

Добавляем:


‘default_phone_region’ => ‘RU’,

Работа с пользователями из UNIX-Shell

В состав nextcloud входит php-скрипт occ, с помощью которого можно управлять сервисом из командной строки Linux.

Добавление пользователя

Создать нового пользователя можно командой:

sudo -u www-data php /var/www/nextcloud/occ user:add admin

* где admin — имя учетной записи.

Сброс пароля

При необходимости сбросить пароль пользователя, можно воспользоваться командой:

sudo -u www-data php /var/www/nextcloud/occ user:resetpassword admin

* где admin — учетная запись пользователя, чей пароль хотим сбросить.

Особенности FPM

Так как интерфейс написан на PHP, то ему свойственны все особенности этого языка и серверов, написанных на нём:

  • Один процесс – один запрос. Это основная особенность кода на PHP. Такое решение подвержено Dos атакам. Например, вы держите сервер, на котором есть 100 процессов FPM. Если одновременно подключить 100 пользователей и заставить их скачивать или загружать какой-либо файл, то 101 пользователь при подключении получить ошибку 504. Связано это с тем, что сервер на FPM не будет обрабатывать новый запрос, пока процессы заняты. 100 клиентов даже могут скачивать небольшой файл, главное – растянуть скачивание, чтобы сервер долго висел. Такая проблема свойственна многим веб-сервисам. Например, Dos уязвимости есть и у Apache.
  • Модули, написанные на PHP, подвержены утечкам памяти. FPM хорошо справляется с этой проблемой, регулируя процессы и их перезапуск.
  • Чем больше процессов вы сделаете, тем больше запросов сможет обработать сервер.
  • FPMможет запускать воркеров в разном окружении и с разными настройками файла php.ini.
  • Если opcode-кэш будет разрушен или повреждён, то FPM сделает экстренную перезагрузку.
  • FPM записывает в логи всё, что происходит на сервере. Благодаря этому вы сможете узнать где возникает ошибка или найти медленно работающий скрипт.

Чистый FPM используется редко, чаще всего применяется связка FPM + NGINX.

Что такое NGINX?

Полное название EngineX –это сервер, разработанный Игорем Сысоевым. Сам автор часто называет своё детище прокси-сервером. NGINX использует протокол HTTPдля работы.

Отличается от Apache и других подобных программ тем, что клиент подключается сначала к прокси-серверу. Этот прокси-сервер передаёт запрос на другую машину, куда изначально хотел попасть клиент. Но это не единственное отличие. NGINX не выполняет тяжёлую работу, поэтому он работает довольно быстро. В основе сервера лежит асинхронно-событийная архитектура.

Конечно же, NGINX не является прокси сервером на самом деле и уж тем более не обеспечивает анонимность работы с программой. Такой название разработчик дал за общий принцип работы прокси и NGINX. Сервер скорее можно назвать конвейером или посредником между запросом пользователя и backend частью программы.

Получая запрос от клиента, NGINX передаёт его FPM-PHP или любой другой библиотеке. Пока FPM занят обработкой переданного ему запроса, NGINX уже работает со следующим пользователем. Такая система не только становится неуязвима к Dosатакам, но начинает работать намного быстрее. Например, NGINX может обрабатывать 1000 и больше запросов в одном процессе.

Точно такая же схема работает с ответами. NGINX получает от backend части ответ и передаёт его пользователю. Получается такой посредник, который быстро перекидывает запросы и ответы от пользователя к серверу.

Также NGINX поддерживает асинхронную работу с файлами. Сегодня скорость чтения и записи файлов с диска достигла больших размеров, поэтому разработчики могут позволить себе обрабатывать файлы в нескольких потоках. Это очень удобно, так как NGINX делит задачу на две части: статичные файлы отправляет на диск, а динамичные запросы отправляет в backend.

Для примера возьмём сервер на Apache, в котором есть 10 процессов, а контента, пусть это будут обычные картинки, у нас 100 штук. В таком случае, пользователю придётся очень долго жать. Пока 10 картинок не обработаются, он не получит следующие 10 и так далее.

Теперь рассмотри такую же ситуацию на NGINX и FPM PHP. У нас по-прежнему остаётся 10 запросов к динамике. Но статичные запросы, а чтение картинки – это статичный запрос, NGINX может обработать самостоятельно, не прибегая к помощи backendчасти. Даже на самой слабой VPSNGINX может работать с 3000 одновременных запросов.

Помимо большой скорости, мы получаем меньший расход оперативной памяти на сервере. Даже голый Apacheбудет потреблять больше ресурсов, чем NGINX и FPMPHP. А вот потребление ресурсов процессора никак не измениться, так как в процессор «засовывают» код на PHP.

Плюсы использования NGINX и FPM PHP

По многим критериям NGINX и FPMPHP выигрывают у Apache.

  • Запросы к статичным объектам обрабатываются в несколько раз быстрее, чем у Apache.
  • Сильно экономиться оперативная память, а значит, экономятся деньги владельца сервера.
  • У NGINX предоставляет много нового функционала, которого нет у Apache.

Однако, все проблемы, которые есть в PHP, останутся с вами. Также в NGINX нет возможности использовать конфигурацию htaccess.

Настройка сервера NGINX и FPM PHP

Перед тем, как настраивать сервер, нужно установить на него CentOS–дистрибутив линукса. Его часто используют при работе с серверами. Также нам понадобится репозиторий EPEL. Чтобы его подключить, используйте команды: # yuminstallepel-release–y.

Теперь обновим все пакеты, которые установлены в системе: # yumupdate–y. После ввода этой команды в терминале появится сообщение, что пакетов не найдено. Так происходит потому, что мы установили чистый дистрибутив.

Устанавливаем NGINX

Установка довольно простая и не займёт много времени. Для начала подключаем репозиторий NGINX:

# rpm -Uvhhttp://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

Цифра «7» после centosозначает версию дистрибутива. Измените цифру, если вы используйте другую версию.

Загружаем пакеты: # yuminstallnginx–y. Если команда выполниться успешно, в терминале появится сообщение «Complete». Теперь запускаем сервер: # systemctlstartnginx, также можно добавить программу в автозагрузку, чтобы сервер стартовал при запуске компьютера: # systemctlstartnginx.

Если вы всё сделали правильно, то при вводе ip-адреса в адресной строке браузера должно появиться приветствие от NGINX. Если этого не произошло, проверьте настройки подключения ещё раз. Проблема может быть скрыта в разрешённых службах или портах. Также проверьте зону Firewalld.

Теперь нужно сделать конфигурационный файл (будем использовать домен build-centos.info):

# mkdir -p /var/www/build-centos.info &&mkdir -p /var/www/build-centos.info/log

Открыть его можно командой: # nano /etc/nginx/conf.d/build-centos.info.conf

В файле нужно прописать настройки для подключения по протоколу https, так как многие SMS системы используют именно этот протокол по умолчанию. Приводить всё содержимое конфигурационного файла здесь не будем, так как он слишком большой. Его код можно найти в интернете.

Установка PHP FPM

Так как в NGINXнет доступа к PHP коду «из коробки», придётся установить FPM отдельно. Для установки будем использовать репозиторий REMI:

# rpm -ivhhttp://rpms.famillecollet.com/enterprise/remi-release-7.rpm

Чтобы сервер работал правильно, найдите и измените файл /etc/yum.repos.d/remi-php74.repo. Значение enabled сделайте равным единице.

Теперь нужно установить FPM: # yuminstallphp-fpm. Эта команда используется для подключения других компонентов. Запускаем сервер и добавляем его в автозагрузку:

# systemctl start php-fpm
# systemctl enable php-fpm

Для проверки сервера вводим команду: # lsof -i:9000. Если всё работает правильно, то в терминале выведется информация о сервере.

PHP FPMдолжен быть запущен через сокет unix. По умолчанию он запускается через адрес 127.0.0.1:9000. Чтобы это исправить, откройте файл /etc/php-fpm.d/www.conf и удалите listen = 127.0.0.1:9000. Вместо него напишите listen = /var/run/php-fpm/php-fpm.sock.

FPM запускается от пользователя apache. Для того чтобы это исправить, в том же файле измените значения user и group на nginx. Теперь перезапустите сервер: # systemctlrestartphp-fpm.

Что такое RoadRunner?

RoadRunner – это сервер для приложений, разработанный компанией SpiralScout. Он появился всего 2 года назад, но уже успел зарекомендовать себя среди разработчиков. Сервер написан на языке Голанг, но прекрасно работает с программами на PHP.

RoadRunner работает по модели load balancer + process manager. Сервер сначала обрабатывает запрос, который поступил от пользователя. Затем, обращается к коду на PHP, предоставляя дальнейшую работу ему.

Серверную часть можно адаптировать под свои задачи. Например, RoadRunner сначала проверит запрос и сообщит об ошибке, если она есть. Таким образом, вы оптимизируете работу своей программы, так как не будете даже запускать код на PHP. Также разработчик может перенести часть кода, требующего много ресурсов, на сервер приложения.

Чем отличается RoadRunner от PHP-FPM+NGINX?

Основное отличие этих серверов в работе с запросами. Связка PHP-FPM+NGINX обеспечивает эффективный менеджер процессов (masterprocess). Менеджер предоставляет воркеров (workerprocess) для обработки запросов, приходящих на сервер. Количество обработчиков постоянно и не меняется со временем.

Воркеры настраиваются отдельно. Каждый из них может обрабатывать определённое количество запросов, но делают они это последовательно, как конвейер. То есть воркер не знает, что у него есть следующий и предыдущий запрос. При каждом новом обращении от клиента обработчик снова начинает загружать базу данных, обращаться к другим ресурсам компьютера, бутстраппить фреймворк и так далее.

Иногда, такая модель эффективна. Например, при «смерти» запроса он не затронет остальные вычисления. Воркер просто загрузит данные для работы и начнёт обрабатывать следующий запрос.

RoadRunner использует другую модель. Воркеры обрабатывают большое количество запросов подряд в цикле. Бутстраппинг происходит только один раз, как и подключение к базе данных. Также разработчик получает возможность перекидывать значение переменных между потоками.

Однако у такого подхода есть и минусы. Коду на PHP часто нужна изоляция для нормальной работы, то есть должны быть зарыты дескрипторы и соединения. В случае с RoadRunner код полностью открыт. Если скрипт вдруг «не умрёт», когда запрос будет выполнен, то возникнет ошибка.

Настройка сервера на RoadRunner

Чтобы собрать сервер, нужно предварительно установить PHP, Голанг и Composer.Сам RoadRunner храниться на GitHub. Чтобы установить его, достаточно скопировать репозиторий:

git clone https://github.com/spiral/roadrunner

Теперь нужно установить зависимости и сам сервер приложений:

cd roadrunner && GO111MODULE=on go mod download
GO111MODULE=on make
GO111MODULE=on make install

Сервер готов к работе. Чтобы протестировать его, создадим одного обработчика. Для этого нужно снова установить зависимости:

composerinit
composerrequirespiral/roadrunner

Теперь опишем работу обработчика. Создаём новый воркер. В этом примере он работает через обычный сокет, но можно использовать протокол TCP.

$worker = new Spiral\RoadRunner\Worker(
new Spiral\Goridge\SocketRelay(“rr.sock”, null, Spiral\Goridge\SocketRelay::SOCK_UNIX)
);
$psr7 = new Spiral\RoadRunner\PSR7Client($worker);

Обрабатываем запрос:

while ($req = $psr7->acceptRequest()) {
try {
$resp = new \Zend\Diactoros\Response();
$resp->getBody()->write(“hello world”);

Обработка ошибок. Если возникнет исключение, нужно закрыть все дескрипторы и соединения.

catch (\Throwable $e) {
$psr7->getWorker()->error((string)$e);
}

Наш воркер готов. Не забудьте перед циклом, в котором обрабатываются запросы, нужно проинициализировать фреймворк, подключиться к БД и так далее. Далее нужно прописать конфигурацию для сервера.

Создаём файл и пишем: # filename: .rr.yaml Далее пишем http, после которого прописываем настройки:

  • Самое важное адрес, на котором будет запущен сервер. Address: :5555.
  • Запускаем обработчик запросов командой: workers:command: “phpworker.php”
  • Указываем как обработчик взаимодействует с сервером (в нашем случае соединение устанавливается через сокет): relay: “unix://rr.sock”
  • Теперь указываем максимальное количество обработчиков и запросов на каждый обработчик: numWorkers: 50 и maxJobs: 200

Конечно, это далеко не все конфигурации, нужные для работы. В реальном проекте конфигурационный файл может состоять из сотни строк. Сервер готов к использованию, осталось только запустить его: rrserve -d –v. После запуска на кран выведется Hellowolrd.

Рекомендации по работе с сервером

Если вы решились перенести свой проект на RoadRunner, обращайте внимание на подключение к базе данных. Лучше создавать новое подключение к БД при каждом запросе либо пристально следить за соединением, чтобы в случае разрыва, откатить транзакцию. Также, в случае потери соединения, нужно закрывать все отрытые файлы.

Утечки памяти – обычное дело для PHP, но, иногда, они становятся слишком существенными. Внимательно следите за кодом, который вы пишете, и подключенными компонентами. Также для борьбы с утечками можно установить значение maxJobs, как в примере выше. Если памяти всё равно расходуется слишком много, очищайте глобальные переменные. Пока обработчик принимает запросы и не вызвана команда dieили exit, никто не будет их очищать.

Переходить на RoadRunner стоит тогда, когда обычных ресурсов NGINX+PHP FPM уже не хватает. Переход не пройдёт бесследно: после подключения сервера приложений ваш код должен быть PSR-7 совместимый. Также у вас не будет возможности использовать большое количество глобальных переменных и сессий.

Скептики часто недоумевают: зачем использовать кашу из GoиPHP, если можно переписать всё приложение сразу на Go, ведь для перехода на RoadRunner придётся приложить много усилий, прежде чем сервер заработает нормально?

Для небольших проектов такое замечание вполне справедливо. Но для больших компаний нецелесообразно увольнять уже сложившуюся команду PHP разработчиков или переучивать их на совершенно другие технологии. Гораздо проще перейти на другой сервер, даже несмотря на то, что он написан на другом языке.