Сначала приведу код полностью. Это не bash-скрипт, а просто список команд, команды выполняются вручную по отдельности, при необходимости вводятся нужные данные.
# Instructions how to setup new AWS EC2 instance with Ubuntu Server 16.04 LTS and install PHP Laravel project and HTTPS
# This is not a bash script, you have to run and control all commands manually
sudo apt-get install nginx mysql-server
sudo mysql_secure_installation
sudo add-apt-repository ppa:ondrej/php && sudo apt-get update
sudo apt-get install php7.1 php7.1-cli php7.1-common php7.1-mysql php7.1-fpm php7.1-curl php7.1-gd php7.1-bz2 php7.1-mcrypt php7.1-json php7.1-tidy php7.1-mbstring php-redis php-memcached php7.1-zip php7.1-dom php7.1-gmp
# run after installation to create config directory from current user
sudo apt-get install mc
mc
sudo mcedit /etc/php/7.1/fpm/php.ini
# cgi.fix_pathinfo=0
sudo systemctl restart php7.1-fpm
sudo mcedit /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
#!
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
#!
location / {
try_files $uri $uri/ /index.php?$query_string;
}
#!
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
}
#!
location ~ /\.ht {
deny all;
}
}
sudo nginx -t
sudo systemctl reload nginx
echo "<?php phpinfo();" | sudo tee /var/www/html/info.php > /dev/null
# check http://11.22.33.44/info.php
sudo rm /var/www/html/info.php
sudo chown -R "$USER":www-data /var/www/
sudo find /var/www/ -type f -exec chmod 660 {} \; && sudo find /var/www/ -type d -exec chmod 2770 {} \;
sudo usermod -a -G www-data ubuntu
# https
sudo apt-get install software-properties-common && sudo add-apt-repository ppa:certbot/certbot && sudo apt-get update && sudo apt-get install python-certbot-nginx
sudo mcedit /etc/nginx/sites-available/default
# server_name my.domain.name;
sudo systemctl reload nginx
sudo certbot --nginx
echo -e '#!/bin/sh\n\ncertbot renew\n' | sudo tee /etc/cron.daily/certbot-renew > /dev/null
sudo chmod 0755 /etc/cron.daily/certbot-renew
sudo certbot renew --dry-run
sudo apt-get install git
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
cd /var && rm -rf www/html
# set repository URL here
git clone ... www
cd www
git checkout dev
ln -s public html
composer install
sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache
sudo chmod -R 0777 storage/framework/cache
cp .env.example .env && php artisan key:generate
# set values in .env file - APP_NAME, DB_DATABASE, and other
Настройка системы
sudo apt-get install nginx mysql-server
sudo mysql_secure_installation
Nginx и MySQL
mysql_secure_installation
задает несколько вопросов по настройке.Would you like to setup VALIDATE PASSWORD plugin? n
Change the password for root? n
Remove anonymous users? y
Disallow root login remotely? y
Remove test database and access to it? y
Reload privilege tables now? y
Если у вас будет один пользователь, с которым проект будет подключаться к базе, то есть постоянное создание пользователей не предусматривается, то плагин валидации паролей можно отключить.
Удаленный логин лучше для всех пользователей отключать, для подключения со своего компьютера можно сделать проброс портов через SSH.
sudo add-apt-repository ppa:ondrej/php && sudo apt-get update
sudo apt-get install php7.1 php7.1-cli php7.1-common php7.1-mysql php7.1-fpm php7.1-curl php7.1-gd php7.1-bz2 php7.1-mcrypt php7.1-json php7.1-tidy php7.1-mbstring php-redis php-memcached php7.1-zip php7.1-dom php7.1-gmp
PHP
PHP 7.1 и 7.2 пока нет в стандартных репозиториях.
sudo apt-get install mc
mc
Midnight Commander
Устанавливать необязательно, если вам больше нравится другой редактор и способ передвижения по файловой системе.
Не стоит после установки запускать в первый раз через
sudo mc
, так как файлы конфигурации создадутся от пользователя root, и при запуске от обычного пользователя будет ошибка доступа.sudo mcedit /etc/php/7.1/fpm/php.ini
# cgi.fix_pathinfo=0
sudo systemctl restart php7.1-fpm
Найти настройку
cgi.fix_pathinfo
, раскомментировать и поставить 0. Это закрытие уязвимости, подробнее можно почитать здесь.sudo mcedit /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
#!
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
#!
location / {
try_files $uri $uri/ /index.php?$query_string;
}
#!
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.1-fpm.sock;
}
#!
location ~ /\.ht {
deny all;
}
}
Восклицательными знаками отмечены места, где надо поменять.
—
index
— добавить index.php
—
try_files
— убрать =404
, добавить /index.php?$query_string
—
location ~ \.php$
— раскомментировать секцию, поменять название файла с сокетом—
location ~ /\.ht
— раскомментировать секцию для файлов *.htaccesssudo nginx -t
sudo systemctl reload nginx
Проверить правильность конфигурации, если все нормально, перезагрузить ее.
echo "<?php phpinfo();" | sudo tee /var/www/html/info.php > /dev/null
# check http://11.22.33.44/info.php
sudo rm /var/www/html/info.php
Создать тестовый файл, проверить работу PHP, потом удалить. Выполнять необязательно.
11.22.33.44
обозначает IP-адрес инстанса.sudo chown -R "$USER":www-data /var/www/
sudo find /var/www/ -type f -exec chmod 660 {} \; && sudo find /var/www/ -type d -exec chmod 2770 {} \;
sudo usermod -a -G www-data ubuntu
Сейчас в веб-каталоге все создано от рута, надо изменить на обычного пользователя. Nginx запускает PHP от пользователя
www-data
из группы www-data
, SSH подключается с пользователем ubuntu
. Надо добавить ubuntu
в эту группу, иначе могут быть проблемы с доступом. Например, когда какая-то консольная команда создает папку, куда будет идти запись и при открытии сайта через веб.Настройка HTTPS
Настройка HTTPS часто делается после настройки проекта, когда он уже есть и работает по HTTP. Но действия общие, от проекта не зависят, поэтому рассмотрим ее раньше.
Используются бесплатные сертификаты от Let's Encrypt.
sudo apt-get install software-properties-common && sudo add-apt-repository ppa:certbot/certbot && sudo apt-get update && sudo apt-get install python-certbot-nginx
Устанавливаем certbot, он обеспечивает настройку и обновление сертификатов.
sudo mcedit /etc/nginx/sites-available/default
# server_name my.domain.name;
sudo systemctl reload nginx
Прописываем доменное имя. Оно уже должно быть доступно и указывать на IP сервера. Для этого в настройках домена у регистратора нужно добавить DNS-запись типа A.
sudo certbot --nginx
Запускаем бота. Он автоматически определит домен по настройкам Nginx, но запросит подтверждение, а также задаст несколько других вопросов. Затем он устанавливает сертификат и обращается по доменному имени для проверки. Настройки Nginx для HTTPS он меняет сам.
echo -e '#!/bin/sh\n\ncertbot renew\n' | sudo tee /etc/cron.daily/certbot-renew > /dev/null
sudo chmod 0755 /etc/cron.daily/certbot-renew
Обновление сертификата надо добавить в cron для ежедневного запуска.
sudo certbot renew --dry-run
Есть специальная команда для проверки, пройдет ли обновление без ошибок.
Настройка проекта
sudo apt-get install git
curl -sS https://getcomposer.org/installer | sudo php -- --install-dir=/usr/local/bin --filename=composer
Git и Composer
Composer лучше не ставить через apt-get, там старая версия. На сайте Composer есть скрипт для более безопасной установки с проверкой хеша. Можно использовать его, или просто взять оттуда текущий хеш и проверить вручную.
cd /var && rm -rf www/html
# set repository URL here
git clone ... www
cd www
git checkout dev
ln -s public html
composer install
Клонируем проект и устанавливаем зависимости. Вставьте свой репозиторий и название ветки.
Nginx настроен на папку
html
, надо ее убрать и сделать симлинк на папку где в проекте находится index.php
. В Laravel это папка public
.sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache
sudo chmod -R 0777 storage/framework/cache
Устанавливаем права на папки специально для Laravel. Подробнее здесь.
cp .env.example .env && php artisan key:generate
Создаем рабочий файл с настройками окружения. Далее все как обычно — создаем, настраиваем, прописываем.
Комментарии (29)
yu-hritsaiy
17.12.2017 20:34Конец 2017, уже все на полную используют контейнеры, может ещё 2 года назад было б актуально
YaRobot
17.12.2017 20:43На продакшене тоже контейнерами оперируете?
У нас как бы HL++ и контейнеры явно лишнее занятие.yu-hritsaiy
17.12.2017 20:59да в проде на aws контейнеры. у кого HL++ тем подобные статьи наверное не нужны, квалификации им хватает, извините, но давайте смотреть трезво на ситуацию.
VolCh
17.12.2017 23:06Они привносят небольшой оверхед в целом, но, субъективно, для подавляющего большинства применений PHP он не значим.
027
17.12.2017 20:37Обновление сертификата надо добавить в cron для ежедневного запуска.
Везде пишут, что надо прописывать в крон руками.
Два раза ставил certbot, оба раза он сделал это сам. ЧЯДНТ?Finesse
18.12.2017 08:46Я ставил certbot на Ubuntu, он после установки попросил меня добавить себя в cron.
Crysdd
17.12.2017 20:37Не помешало бы осветить добавление второго домена на сервер. Я полагаю, certbot читает не только дефолтный конфиг?
michael_vostrikov Автор
17.12.2017 20:53Я с такими не работал, но вроде можно запустить certbot повторно и выбрать другой домен, то есть будет 2 сертификата. Можно один сертификат на 2 имени сделать, но я так делал только для алиасов основного.
027
17.12.2017 21:07Можно запускать повторно, многократно и даже несколько доменов за один раз через пробел.
Hixon10
17.12.2017 22:27А если хочется nginx (или аналог) + docker + https в пару строк, то:
github.com/evertramos/docker-compose-letsencrypt-nginx-proxy-companion
github.com/umputun/nginx-le
traefik.io
caddyserver.comshizo
18.12.2017 12:25Да, хороший вариант. О нем же от/для Google Cloud cloud.google.com/community/tutorials/nginx-reverse-proxy-docker
arround
18.12.2017 04:27Запускать certbot раз в сутки…
grossws
18.12.2017 15:07Но ничего особо страшного в этом нет, он проверяет срок действия сертификата и не дёргает сервер, если ещё достаточно времени осталось.
arround
19.12.2017 20:21Просто нет смысла, раз в месяц вполне адекватно
sav1812
20.12.2017 00:18Читаем рекомендацию на сайте Cerbot:
Note:
if you're setting up a cron or systemd job, we recommend running it twice per day (it won't do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let's Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.
michael_vostrikov Автор
18.12.2017 17:17В документации вообще 2 раза в день советуют запускать.
Note:
if you're setting up a cron or systemd job, we recommend running it twice per day (it won't do anything until your certificates are due for renewal or revoked, but running it regularly would give your site a chance of staying online in case a Let's Encrypt-initiated revocation happened for some reason). Please select a random minute within the hour for your renewal tasks.
Timonych
18.12.2017 19:40Ваша неправда, касательно наличия DNS записи с A.
У меня основной домен hms.fun, в котором есть только запись CNAME, с маской *.michael_vostrikov Автор
18.12.2017 20:06Сервис проверки DNS говорит, что CNAME hms.fun указывает на запись timonych.mykeenetic.ru типа A. Понятно, что алиасы и поддомены можно по-разному создавать, но изначальная запись A должна где-то быть. Или если у заказчика уже есть mydomain.com с блогом или landing page, то для api.mydomain.com тоже нужна запись A.
Timonych
18.12.2017 20:34Начальная запись однозначно где-то должна быть, чтобы ссылаться на конкретный IP, но в данном случае, у меня белый динамический, и CNAME в данном случае идеальный выход, при условии, что не надо заморачиваться с поддоменами в DNS записях.
grossws
19.12.2017 22:56CNAME на верхнем уровне сильно не рекомендуется, многие DNS-провайдеры её явно запрещают. AFAIK, это просто не разрешено стандартами, но проверять RFC сейчас лень.
Shtucer
Собственно, и перед этим все как обычно.
michael_vostrikov Автор
Да, для людей, знакомых с администрированием Linux, ничего нового здесь нет.
Под «обычно» я имел в виду то, что и локально делается, на машине для разработки.
Shtucer
Не обязательно. Тыщи этих мануалов. Только в вашем заголовке упоминается AWS(кстати, зачем? ничего AWS специфичного в статье не заметил) и это всё отличие.
michael_vostrikov Автор
В принципе да, подойдет для любой системы, если есть Ubuntu и публичный IP. Просто я эти инструкции составил для себя при работе с AWS.
2 статьи, указанные до ката, немного устарели, пришлось кое-что отдельно искать. Вот и решил собрать все в одном месте.