Деплой програми на Laravel 7 на Ubuntu & Nginx

Деплой програми на Laravel 7 на Ubuntu & Nginx

Вирішив я тут своє портфоліо зробити на Laravel 7. Щоб головна сторінка була лендингом, а всю інформацію на ній можна було міняти за допомогою адмінки. Не суть. Справа дійшла до деплою. Знайшов пару хороших туторіалів, як це зробити на повноцінному сервері з усіма проблемами. У деплої я не дуже сильний, я взагалі більший фронт, ніж фулстек. І, якщо писати та тестувати на PHP я ще можу, то до керування сервером тощо. я ще не доріс. Але довелося розумітися.

Зараз пройдемося з усіх кроків, починаючи із запуску через SSH і закінчуючи робочим сайтом. Постараємося обійти все підводне каміння.

Можливо, ви зможете знайти аналогічні вказівки в інтернеті. Адже я зрештою знайшов. Правда не в одному місці, не без допомоги StackOverflow і навряд чи російською. Я помучився. Тож вирішив вам життя спростити.

Робити ми все будемо із дроплетом на DigitalOcean. Це, звичайно, необов'язково, вибирайте будь-який хостинг. Дійдете до робочого сервера на Ubuntu, повертайтесь. Для тих, хто все ж таки вирішив робити на DigitalOcean, будуть ще поради з настроювання домену. А також реферальне посилання на 100 $.

Всі специфічні для DigitalOcean кроки будуть дані у подібних виносках.

Почнемо.

TL;DR (тільки основні команди)

Створюємо користувача

  • ssh root@[IP-адрес вашего дроплета]
  • adduser laravel
  • usermod -aG sudo laravel
  • su laravel

Додаємо йому SSH

  • mkdir ~/.ssh
  • chmod 700 ~/.ssh
  • vim ~/.ssh/authorized_keys
  • Вставляємо публічний ключ
  • chmod 600 ~/.ssh/authorized_keys

Фаєрвол

  • sudo ufw allow OpenSSH
  • sudo ufw enable
  • sudo ufw status

Nginx

  • sudo apt update
  • sudo apt install -y nginx
  • sudo ufw allow 'Nginx HTTP'
  • sudo ufw status

MySQL

  • sudo apt install -y mysql-server
  • sudo mysql_secure_installation, NYNNY
  • sudo mysql
  • ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<Ваш пароль для MySQL>';
  • SELECT user,authentication_string,plugin,host FROM mysql.user;
  • FLUSH PRIVILEGES;
  • exit

PHP

  • sudo apt update

  • sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https

  • sudo apt-add-repository ppa:ondrej/php

  • sudo apt update

  • 7.3: sudo apt install -y php7.3-fpm php7.3-mysql

  • 7.4: sudo apt install -y php7.4-fpm php7.4-mysql

  • sudo vim /etc/nginx/sites-available/<Ваш домен>

Базове налаштування:

server {
        listen 80;
        root /var/www/html;
        index index.php index.html index.htm index.nginx-debian.html;
        server_name <Ваш домен или IP>;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ .php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        }

        location ~ /.ht {
                deny all;
        }
}

Тільки HTTP налаштування під Laravel:

server {
    listen 80;
    listen [::]:80;

    root /var/www/html/<Имя проекта>/public;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name <Ваш домен или IP>;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /.ht {
        deny all;
    }
}

HTTPS налаштування під Laravel:

server {
    listen 80;
    listen [::]:80;

    server_name <Ваш домен> www.<Ваш домен>;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name <Ваш домен> www.<Ваш домен>;
    root /var/www/html/<Имя проекта>/public;

    ssl_certificate /etc/letsencrypt/live/<Ваш домен>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<Ваш домен>/privkey.pem;

    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers on;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php index.html index.htm index.nginx-debian.html;

    charset utf-8;

    location / {
            try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /.ht {
            deny all;
    }

    location ~ /.well-known {
            allow all;
    }
}

  • sudo ln -s /etc/nginx/sites-available/<Ваш домен> /etc/nginx/sites-enabled/
  • sudo unlink /etc/nginx/sites-enabled/default
  • sudo nginx -t
  • sudo systemctl reload nginx

Laravel

  • 7.3: sudo apt install -y php7.3-mbstring php7.3-xml composer unzip

  • 7.4: sudo apt install -y php7.4-mbstring php7.4-xml composer unzip

  • mysql -u root -p

  • CREATE DATABASE laravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

  • GRANT ALL ON laravel.* TO 'root'@'localhost' IDENTIFIED BY '<Ваш пароль от MySQL>';

  • FLUSH PRIVILEGES;

  • exit

  • cd /var/www/html

  • sudo mkdir -p <Имя проекта>

  • sudo chown laravel:laravel <Имя проекта>

  • cd ./<Имя проекта>

  • git clone <ссылка на проект> . / git clone -b <имя ветки> --single-branch <ссылка на проект> .

  • composer install

  • vim .env

APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=http://<Ваш домен>

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<Ваш пароль от MySQL>

  • php artisan migrate

  • php artisan key:generate

  • sudo chown -R $USER:www-data storage

  • sudo chown -R $USER:www-data bootstrap/cache

  • chmod -R 775 storage

  • chmod -R 775 bootstrap/cache

HTTPS

  • sudo add-apt-repository ppa:certbot/certbot

  • sudo apt install -y python-certbot-nginx

  • sudo certbot certonly --webroot --webroot-path=/var/www/html/<Имя проекта>/public -d <Ваш домен> -d www.<Ваш домен>

  • sudo nginx -t

  • sudo ufw allow 'Nginx HTTPS'

  • sudo ufw status

  • sudo systemctl reload nginx

Створюємо дроплет на DigitalOcean та реєструємо новий SSH-ключ

Я щиро вірю, що ви самі розберетеся із реєстрацією на DigitalOcean. Вона непроста, з купою верифікацій та іншої байди. Якщо у вас при верифікації за допомогою документів постійно виникає помилка мережі, спробуйте все зробити через VPN, має допомогти.

У меню зверху натискаємо Створювати->Краплі. Вибираємо Ubuntu.

Як тільки зареєструвалися, ви отримаєте 100 $ на рахунок. Але не спокушайтеся. У вас є лише 60 днів, щоб їх витратити. А це дуже мало. Ви можете, як і я, захотіти використати план дорожче, щоб потім, коли вже підуть реальні гроші, пересісти дешевше. Відразу говорю, не вийде. Збільшувати можна, зменшувати не можна. Такі справи. Я обираю стандарт->$5.

Регіон я вибираю найближчий до нас Франкфурт-на. Мережа VPC->default-fra1

Аутентифікацію одразу зробимо через SSH. Натискаємо New SSH Key. Якщо у вас немає SSH, праворуч є дуже проста інструкція. Відкриваємо bash-термінал, вставляємо ssh-keygen. Потім заходимо у файл із публічним ключем /Users/<Ваше имя пользователя>/.ssh/id_rsa.pub (або просто cat ~/.ssh/id_rsa.pub), копіюємо вміст та вставляємо у вікно зліва. Ім'я будь-яке.

Вигадуємо для дроплета хостнейм.

натискаємо Create Droplet

Створюємо нового користувача

  • ssh root@[IP-адрес вашего дроплета]
  • Чи ви хочете, щоб виконати connecting (yes/no/[fingerprint])? yes
  • Введіть пароль від SSH
  • Створюємо користувача Laravel: adduser laravel
  • Введіть пароль та іншу інформацію (я вводжу лише Full Name)
  • Додаємо користувача до групи sudo: usermod -aG sudo laravel

SSH для нового користувача

  • Перемикаємося на нового користувача: su laravel

Всі дії далі, до кінця статті, ми проводимо від імені користувача laravel. Тому, якщо ви раптом перервалися, перезайдіть та введіть su laravel

  • mkdir ~/.ssh
  • chmod 700 ~/.ssh
  • vim ~/.ssh/authorized_keys

Ми відкрили файл у Vim. Якщо ви з ним не знайомі взагалі, можете працювати в Nano, ваше право.

Найбільш базові команди Vim

Щоб по ходу статті користуватися редактором Vim, вам достатньо знати наступне.

  • У Vim є різні режими: звичайний (Normal mode), у якому ви вводите команди і вибираєте режими та інші.
  • Щоб вийти з будь-якого режиму та потрапити у звичайний режим, достатньо натиснути Esc
  • Пересуватися: можна просто стрілками
  • Вийти без збереження <Normal mode>: :q!
  • Вийти та зберегти <Normal mode>: :wq
  • Перейти до режиму введення тексту <Normal mode>: i (Від англ. вставити)
  • Вставляємо наш публічний ключ (який ми робили вище)
  • Захищаємо від змін: chmod 600 ~/.ssh/authorized_keys

Встановлюємо фаєрвол

  • Дивимося всі доступні налаштування: sudo ufw app list
  • Дозволяємо OpenSSH (інакше нас залочить): sudo ufw allow OpenSSH
  • Запускаємо фаєрвол: sudo ufw enable, y
  • перевіряємо: sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Все в порядку.

Встановлюємо Nginx

При встановленні вас іноді запитуватиме "Ви впевнені?". Відповідайте y (ну тільки якщо впевнені).

  • sudo apt update
  • sudo apt install nginx

Додаємо Nginx у налаштування фаєрволу

  • sudo ufw app list
  • sudo ufw allow 'Nginx HTTP'
  • sudo ufw status

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Перейдіть по IP. Якщо все йде добре, ви повинні побачити таке.

Деплой програми на Laravel 7 на Ubuntu & Nginx

Встановлюємо MySQL

  • sudo apt install mysql-server
  • Запускаємо автоматичний скрипт захисту sudo mysql_secure_installation

Дайте відповідь на поставлені питання. Якщо ви не знаєте, що відповідати, ось рекомендовані варіанти:

  • Validate password plugin N

  • Remove anonymous users? - Y

  • Disallow root login remotely? - N

  • Remove test database and access to it? - N

  • Reload privilege tables now? - Y

  • Заходимо в MySQL: sudo mysql

  • Дивимося методи доступу: SELECT user,authentication_string,plugin,host FROM mysql.user;

  • Встановлюємо пароль для root: ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '<Ваш пароль для MySQL>';

  • Дивимося методи доступу знову: SELECT user,authentication_string,plugin,host FROM mysql.user;

  • Застосовуємо зміни та виходимо з MySQL: FLUSH PRIVILEGES; и exit

  • Тепер, щоб увійти до MySQL потрібно використовувати mysql -u root -p та вводити пароль

Встановлюємо PHP

Скористаємося стороннім репозиторієм від Ондржей Сури

  • sudo apt update
  • sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https
  • sudo apt-add-repository ppa:ondrej/php
  • sudo apt update

Тепер вибираємо. Для Laravel 7 можна вибрати PHP 7.3 чи 7.4. Відмінність буде лише у цифрах 3 та 4.

  • 7.3: sudo apt install -y php7.3-fpm php7.3-mysql
  • 7.4: sudo apt install -y php7.4-fpm php7.4-mysql

PHP FastCGI Process Manager (fpm) працює з запитами PHP. mysql, природно, до роботи з MySQL.

Далі я все робитиму на 7.4.

Налаштовуємо Nginx

  • sudo vim /etc/nginx/sites-available/<Ваш домен>

Замість "<Ваш домен>" впишіть домен (наприклад, mysite.ru), який хочете використовувати у майбутньому. Якщо у вас такого поки що немає, пишіть будь-який, потім просто повторіть дії в цьому розділі для свого домену, коли оберіть його.

Вписуємо наступне:

server {
        listen 80;
        root /var/www/html;
        index index.php index.html index.htm index.nginx-debian.html;
        server_name <Ваш домен или IP>;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ .php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        }

        location ~ /.ht {
                deny all;
        }
}

Якщо Ви обрали версію 7.3 замість php7.4-fpm.sock впишіть php7.4-fpm.sock.

Слухаємо 80 порт на server_name, коли приходимо запит докорінно /var/www/html беремо index-файл. Якщо після server_name щось є, шукаємо такий файл. Не знаходимо, викидаємо 404. Якщо закінчується на .php, проганяємо через fpm. Якщо є .ht, забороняємо (403).

  • Робимо посилання з sites-available в sites-enabled: sudo ln -s /etc/nginx/sites-available/<Ваш домен> /etc/nginx/sites-enabled/
  • Видаляємо посилання на default: sudo unlink /etc/nginx/sites-enabled/default
  • Перевіряємо на помилки: sudo nginx -t
  • Перезавантажуємо: sudo systemctl reload nginx

Перевіряємо роботу:

  • sudo vim /var/www/html/info.php
  • Пишемо: <?php phpinfo();
  • Переходимо на <Ваш IP>/info.php

Ви повинні побачити щось подібне:

Деплой програми на Laravel 7 на Ubuntu & Nginx

Тепер цей файл можна видалити: sudo rm /var/www/html/info.php

Ставимо Laravel

  • 7.3: sudo apt install php7.3-mbstring php7.3-xml composer unzip

  • 7.4: sudo apt install php7.4-mbstring php7.4-xml composer unzip

  • Заходимо в MySQL: mysql -u root -p

  • Створюємо БД з ім'ям Laravel: CREATE DATABASE laravel DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

  • Надаємо root доступ до Laravel: GRANT ALL ON laravel.* TO 'root'@'localhost' IDENTIFIED BY '<Ваш пароль от MySQL>';

  • FLUSH PRIVILEGES;

  • exit

  • cd /var/www/html

  • Створюємо папку для проекту: sudo mkdir -p <Имя проекта>

  • Надаємо користувачеві Laravel права на проект: sudo chown laravel:laravel <Имя проекта>

Далі слід перенести проект. Наприклад, клонування з Github.

  • cd ./<Имя проекта>
  • git clone <ссылка на проект> .

Варто враховувати, що, якщо ви не зберігали статичні файли (наприклад, з /public) на Github, то їх у вас, звісно, ​​не буде. Я, наприклад, для вирішення цього створив окрему гілку deploy, з якої вже й клонував: git clone -b <имя ветки> --single-branch <ссылка на проект> ..

  • Встановлюємо залежності: composer install
  • Створюємо .env: vim .env

Базова версія його виглядає так:

APP_NAME=Laravel
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=http://<Ваш домен>

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=<Ваш пароль от MySQL>

Якщо ви копіюєте свій .env, замініть APP_ENV на production, APP_DEBUG на false і впишіть правильні налаштування MySQL.

  • Мігруємо БД: php artisan migrate
  • Генеруємо код: php artisan key:generate

Змінюємо дозволи:

  • sudo chown -R $USER:www-data storage
  • sudo chown -R $USER:www-data bootstrap/cache
  • chmod -R 775 storage
  • chmod -R 775 bootstrap/cache

Останнє, що залишилося, – переналаштувати Nginx під Laravel:

sudo vim /etc/nginx/sites-available/<Ваш домен>

server {
    listen 80;
    listen [::]:80;

    root /var/www/html/<Имя проекта>/public;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name <Ваш домен или IP>;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /.ht {
        deny all;
    }
}

Як і минулого разу, якщо Ви обрали версію 7.3 замість php7.4-fpm.sock впишіть php7.4-fpm.sock.

Налаштування домену на DigitalOcean

Все насправді дуже просто. Ви купуєте домен (де завгодно), переходьте на DigitalOcean в Створювати->Domains/DNS. В полі Додайте домен ви вписуєте цей домен, натискаєте додати. Потім переходьте в налаштування домену та в поле ІМЯ ГОСПОДА вписуєте @. Вибираєте проект та натискаєте Створити запис.
Тепер переходьте на сайт, де купували домен, знаходите там "DNS Сервери" (або щось подібне) та вписуєте сервери DigitalOcean (а саме ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com). Тепер треба трохи (або багато) почекати, доки ці налаштування будуть прийняті. Готово!
Єдина проблема – у вас сайт відкриватиметься лише як HTTP. Щоб HTTPS, переходимо до наступної частини.

Налаштовуємо HTTPS

Встановлюємо certbot та передаємо йому ім'я домену (формату mysite.ru) та ім'я домену з www (www.mysite.ru).

  • sudo add-apt-repository ppa:certbot/certbot
  • sudo apt install python-certbot-nginx
  • sudo certbot certonly --webroot --webroot-path=/var/www/html/<Имя проекта>/public -d <Ваш домен> -d www.<Ваш домен>

Тепер треба переналаштувати Nginx (не забудьте підставити свої значення):

server {
    listen 80;
    listen [::]:80;

    server_name <Ваш домен> www.<Ваш домен>;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name <Ваш домен> www.<Ваш домен>;
    root /var/www/html/<Имя проекта>/public;

    ssl_certificate /etc/letsencrypt/live/<Ваш домен>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<Ваш домен>/privkey.pem;

    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
    ssl_prefer_server_ciphers on;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header X-Content-Type-Options "nosniff";

    index index.php index.html index.htm index.nginx-debian.html;

    charset utf-8;

    location / {
            try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /.ht {
            deny all;
    }

    location ~ /.well-known {
            allow all;
    }
}

Думаю, ви вже зрозуміли, що потрібно змінити для PHP 7.3.

Тут насправді все просто. Ми просто надсилаємо всі запити з HTTP (порт 80) на HTTPS (порт 443). А там робимо все те саме, що й раніше, але вже із шифруванням.

Залишилося поставити дозволи у фаєрволі:

  • sudo nginx -t
  • sudo ufw app list
  • sudo ufw allow 'Nginx HTTPS'
  • sudo ufw status
  • sudo systemctl reload nginx

Тепер все має працювати як треба.

[Додатково] Встановлення Node.js

Якщо вам знадобилося запускати npm-команди прямо на сервері, вам потрібно встановити Node.js.

  • sudo apt update
  • sudo apt install -y nodejs npm
  • nodejs -v

Я зупинився на цьому етапі. В принципі результат мене влаштовує. Можливо, я перейду з DigitalOcean кудись ближче до Росії і дешевше. Але оскільки я вже пройшов усі круги верифікації на сайті і все робив там, я показував на їхньому прикладі. До того ж, їх стартові 100 доларів – відмінний плацдарм для тренувань.

PS Окрема подяка автору ось цього гіста, який послужив основою всіх перерахованих вище дій. Він у деяких моментах не працює для Laravel 7, я це виправив.

PPS Якщо ви раптом топовий інженер, який думає командами з bash, будь ласка, не судіть суворо. Можливо, вам рівень цієї статті здасться занизьким, але я був би радий знайти таку, коли вона мені була потрібна. Якщо є пропозиції щодо покращення, я обома руками "за".

Джерело: habr.com

Додати коментар або відгук