Максим Кузнецов

Простыми словами о веб-разработке.

Эгея | Основы веба | Как стать веб-разработчиком
Docker | Веб-сервер | PHP | Базы данных

Установка и настройка Clickhouse на EC2

Нашёл отличный и исчерпывающий гайд по установке и подготовке Clickhouse для продакшена на AWS EC2.
Допустим, у нас уже есть VPC, в которую хочется добавиться сервер с CH.
Единственно, в качестве инстанса я взял машину попроще — m7g.large (~$60/mo) на Ubuntu и Arch64 архитектуре.

https://anthonynsimon.com/blog/clickhouse-deployment/

Как узнать общий вес базы данных и найти самые тяжёлые таблицы

Вес баз данных

SELECT table_schema AS "Database", 
ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS "Size (GB)" 
FROM information_schema.TABLES 
GROUP BY table_schema;

Размер таблиц, включая отдельно данные и отдельно индексы.

SELECT CONCAT(table_schema, '.', table_name),
       CONCAT(ROUND(table_rows / 1000000, 2), 'M')                                    `rows`,
       CONCAT(ROUND(data_length / ( 1024 * 1024 * 1024 ), 2), 'G')                    DATA,
       CONCAT(ROUND(index_length / ( 1024 * 1024 * 1024 ), 2), 'G')                   idx,
       CONCAT(ROUND(( data_length + index_length ) / ( 1024 * 1024 * 1024 ), 2), 'G') total_size,
       ROUND(index_length / data_length, 2)                                           idxfrac
FROM   information_schema.TABLES
ORDER  BY data_length + index_length DESC
LIMIT  20;

Как добавить новый сервис в systemd/systemctl и запускать его при старте Ubuntu

Задача

Есть docker-compose файл, поднимающий Zabbix. Есть небольшая обёртка в виде Makefile, которая позволяет запускать и останавливать docker-compose. Нужно добавить запуск этой команды при старте/рестарте системы.

Дано

Всё лежит в `/var/www/zabbix-server/`.
Содержание файла Makefile:

...
docker-up:
        docker-compose up -d

docker-down:
        docker-compose stop

Решение

  1. Создать новый файл `vim /etc/systemd/system/zabbix.service`.
[Unit]
Description=Run Zabbix Docker Containers on Startup

[Service]
RemainAfterExit=True
Restart=always
RestartSec=1
WorkingDirectory=/var/www/zabbix-server
ExecStart=/usr/bin/make docker-up
ExecStop=/usr/bin/make docker-down

[Install]
WantedBy=default.target
  1. chmod 644 /etc/systemd/system/zabbix.service
  2. systemctl enable zabbix.service
  3. systemctl start zabbix.service

Ubuntu: Running Out of Space и количество inodes

Одна из причин, почему ваш Ubuntu сервер может сигнализировать, что кончилась память, тогда как её предостаточно — слишком большое количество файлов. Каждый диск в зависимости от размера имеет ограниченное максимальное количество файлов и папок, которые вы можете создать.

Проверить количество используемых inodes можно командой:

root@ec2-consumer:~# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/root        2.5M  2.1M  419K   84% /
devtmpfs         482K   349  482K    1% /dev
tmpfs            484K     5  484K    1% /dev/shm
tmpfs            484K   602  483K    1% /run
tmpfs            484K     4  484K    1% /run/lock
tmpfs            484K    18  484K    1% /sys/fs/cgroup
/dev/loop1         16    16     0  100% /snap/amazon-ssm-agent/4046
/dev/loop5        11K   11K     0  100% /snap/core18/2253
/dev/nvme1n1      25M  462K   25M    2% /var/www
tmpfs            484K    22  484K    1% /run/user/0

Видим 84% около /dev/root — процент очень большой, это свидетельствует о проблеме. Обычно должно быть не больше 50%, а 80% — это верхний предел.

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

Если не знаете, где превышаете лимит по количеству файлов, запустите команду (может занять несколько минут):

du --inodes -d 3 / | sort -n | tail

Быстрое решение

Просто удалите лишние файлы. Это можно сделать по шаблону regexp:

find /tmp -type f -mtime +0 -name 'phrets*' -execdir rm -- '{}' \;

Здесь -mtime +0 фильтрует все файлы, которые были созданы больше суток назад — я не хотел удалять все файлы, так как не был уверен, что библиотека phrets не использует самые свежие для чего-то нужного (хотя они все и были пустыми). Почитайте про значения параметра mtime, чтобы фильтровать как давно созданные файлы, так и недавно.

Долгое решение

Нужно увеличить количество inodes. Это крайне редкое и радикальное решение, которое хорошо описано тут — https://www.ctrl.blog/entry/how-to-all-out-of-inodes.html.

Как узнать размер бакета на AWS S3

К сожалению, AWS консоль (дэшборд) не даёт возможность узнать количество файлов и занимаемый объём. Это можно сделать через консоль:

aws s3 ls --summarize --human-readable --recursive s3://<bucket-name>

Бесплатный wildcard SSL-сертификат для поддоменов

Для простых веб-приложений достаточно одного домена (example.com). Однако для сложных систем, с разделением на бэкенд и фронтенд части, с лендингами, микросервисами и т. п. нужны поддомены, например: api.example.com, app.example.com, cdn.example.com.

Вместо того, чтобы выпускать отдельные сертификаты на каждый поддомен, мы можем выпустить один сертификат, покрывающий сразу все кейсы — *.example.com. Такой тип сертификатов называется Wildcard.

Как и в предыдущей статье про выдачу бесплатного SSL-сертификата, мы воспользуемся утилитой Certbot, который поможет нам выпустить и установить бесплатные SSL-сертификаты для наших поддоменов через центр Let’s encrypt.

Предполагаю, что вы уже настроили ваш сервер, чтобы поддомены были доступны по http (80 порт). Если вы не знаете, как это сделать, поищите статью по вашим ОС и веб-серверу на Digitalocean. Например, вот статья про установку и настройку Nginx на Ubuntu 20.04.

Заходим на сайт Certbot’а и выбираем ОС нашего сервиса и веб-сервер. Ниже в примере будет Ubuntu 20.04 и Nginx. Дальше выбираем таб Wildcard.

Предположим, что нам нужны следующие домены: example.com, api.example.com и app.example.com.
Запускаем по инструкции первые 8 шагов для установки самой утилиты:

// Удаляем snap, если он был установлен ранее
$ sudo apt-get remove certbot
// Устанавливаем snap
$ sudo snap install core; sudo snap refresh core
// Устанавливаем certbot
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
$ sudo snap set certbot trust-plugin-with-root=ok

// Проверяем, что certbot установлен
$ certbot --version
> certbot 1.14.0

Для того, чтобы выпустить сертификаты, мы должны доказать удостоверяющему центру Let’s Encrypt, что мы действительно владеем данными доменами и сабдоменами. Есть два способа это сделать.

  1. Добавить в DNS специальные txt записи, которые попросит нас добавить Let’s Encrypt, после этого он их проверит, и если записи будут обнаружены, это подтвердит факт владения (или по крайней мере доступа к ним). С чужими доменами так сделать не получится.
  2. Webroot. Аналогичный способ, но специальные уникальные строки добавляются в файлы, которые потом должны быть доступны через URL, например: http://api.example.com/.well-known/acme-challenge/JH1kjoemxaS33d. Поскольку такой файл сможет добавить только владелец домена, этого тоже достаточно, чтобы Let’s Encrypt удостоверился в факте нашего владения.

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

Certbot поддерживает из коробки несколько популярных DNS-регистраторов (те сервисы, где можно купить домен), и тогда можно следовать по инструкции, однако в моём случае регистратором был Godaddy, который не поддерживается. Поэтому я воспользовался вторым способом и он оказался даже проще первого. Кроме того, данный способ надёжнее, так как не зависит, повезёт ли вам с поддержкой вашего регистратора или нет.

Для верификации доменов по webroot нам нужно настроить каждый домен/поддомен, чтобы он отдавал директорию /.well-known/acme-challenge/. В эту папку certbot запишет то, что нужно Let’s Encrypt, чтобы мы прошли проверку, поэтому убедитесь, что certbot имеет туда доступ.

Есть небольшой лайфхак, как упростить работу с этой папкой в конфигах сервера. Для этого мы создадим отдельный файл конфига, который будем подключать для каждого домена/поддомена. Пример для Nginx:

// создаём файл "/etc/nginx/letsencrypt.conf"
location /.well-known/acme-challenge {
    # Вместо `/var/www/acme-challenge` можно указать любую папку.
    # Она может быть недоступна извне, это неважно. Главное, чтобы туда имел доступ ваш текущий юзер.
    alias /var/www/acme-challenge/.well-known/acme-challenge;
}

Подключаем этот файл в конфигах доменов и поддоменов. Допустим, у вас есть файл /etc/nginx/sites-available/api.example.com (с остальными аналогично).

server {
    server_name api.example.com;
    include letsencrypt.conf;
    ...
}

Готово. Теперь домен будет все запросы, начинающиеся на /.well-known/acme-challenge будут направлены в папку /var/www/acme-challenge/.well-known/acme-challenge, общую для всех доменов/поддоменов.

Далее запускаем certbot, чтобы он пообщался с Let’s Encrypt, подтвердил наши домены, выпустил сертификаты и даже настроил наш веб-сервер на их использование.

certbot run -a webroot -i nginx -w /var/www/acme-challenge -d example.com -d api.example.com -d app.example.com

Разберём эти конфиги:

  • -a webroot — это способ аутентификации (подтверждение, что мы владеем доменами)
  • -i nginx — один из доступных способов установки сертификатов. В данном случае это nginx, так как именно этот веб-сервер мы используем. Certbot вам задаст несколько вопросов и после этого обновит конфиги. Делает он это очень умно, так что без разницы как эти конфиги у вас написаны. И даже устанавливает редирект http на https.
  • -w /var/www/acme-challenge — путь до папки, которая будет использоваться для webroot аутентификации. Обратите внимание, что именно эта папка прописана в /etc/nginx/letsencrypt.conf.
  • -d example.com -d api.example.com -d app.example.com — указываем все необходимые поддомены, обязательно первым указываем основной домен (не поддомен), иначе ничего не получится.

Всё, certbot всё сделал сам, даже перезагрузил веб-сервер. Можно зайти через браузер на поддомены и убедиться, что всё работает.


p.s. если браузер выдаёт ошибку, что такой домен не найден, то проверьте, что файрволл настроен на выдачу https трафика. Например, в Ubuntu 20.04 это делается через UFW:

// Проверяем, есть ли HTTPS в активных правилах
$ sudo ufw status
// Смотрим, какие правила могут быть включены
$ sudo ufw app list
// Включаем Nginx https
$ sudo ufw allow 'Nginx HTTPS'
// Проверяем, что правило появилось в активных
$ sudo ufw status

Как настроить php-cs-fixer и phpstan на локалке

Проблема 1

При совместной разработке (от 2х человек) code style становится критичным. Если каждый будет писать в своём стиле, вскоре проект превратится в бардак, где по разному стилю можно будет оценивать возраст кода будто по кольцам на деревьях.

На собеседованиях я часто слышу от кандидатов, что мы пользуемся проверками, встроенными в IDE. Но это полрешения, так как такие проверки носят рекомендательный, а не обязательный характер. Очень легко не заметить предложение по правке от IDE. А кроме того, приходится синхронизировать настройки IDE между всей командой. А что делать, если у кого-то другой редактор? Результат непредсказуем, а значит и ненадёжен.

Проблема 2

Чем больше кодовая база проекта, тем проще допустить ошибку или опечатку. Вручную проверка кода перед каждым коммитом возможна, но требует много времени и большой внимательности. Результат опять непредсказуем и ненадёжен.

Решение

Нужно договориться об общих правилах с командой и автоматизировать процесс проверки кода, сделав её независимой от IDE, платформы, настроения, желания и внимательности человека.

Такие инструменты уже есть — code style и статические анализаторы кода.

Единый стиль кода

Поскольку я специализируюсь на Symfony, то для код-стайла выбираю PHP-CS-Fixer. Он написан при участии создателя Symfony и имеет из коробки поддержку рекомендованного сообществом Symfony Code Standards. Есть ещё PHPCodeSniffer, но он умеет только обнаруживать ошибки, но не исправляет их автоматически, поэтому я рекомендую именно PHP-CS-Fixer.

Совет: обязательно изучите и следуйте code style и рекомендациям вашего фреймворка. С большой вероятностью в будущих проектах вам встретится именно общепринятый в сообществе фреймворка code style, поэтому будет проще вписаться в новую команду, если вы придёте к этому стилю как можно раньше. К тому же, уже принятый в сообществе стиль поможет избежать ненужных холиваров внутри команды.

Устанавливаем через composer и настраиваем PHPCSFixer в Symfony-проекте:

cd /ваш/проект
composer req --dev friendsofphp/php-cs-fixer
# Если используете docker-compose, то устанавливайте в нём
docker-compose exec web composer req --dev friendsofphp/php-cs-fixer

Создаём в корне проекта файл .php_cs:

<?php

$finder = PhpCsFixer\Finder::create()
    ->in([
        __DIR__ . '/src',
        __DIR__ . '/tests'
    ])
;

return PhpCsFixer\Config::create()
    ->setRules([
        '@Symfony' => true,
        'array_syntax' => ['syntax' => 'short'],
        'concat_space' => ['spacing' => 'one'],
        'increment_style' => ['style' => 'post'],
        'no_extra_blank_lines' => ['tokens' => [
            'extra',
            'parenthesis_brace_block',
            'square_brace_block',
            'throw',
            'use',
        ]],
        'no_superfluous_phpdoc_tags' => false,
        'phpdoc_align' => false,
        'phpdoc_annotation_without_dot' => false,
        'trailing_comma_in_multiline_array' => false,
        'yoda_style' => false
    ])
    ->setFinder($finder)
;

Теперь вы можете запустить проверку всего проекта (или конкретного пути) с помощью команды

# только поиск ошибок
./vendor/bin/php-cs-fixer  fix --dry-run --diff ./
# поиск ошибок и их автоматический фикс
./vendor/bin/php-cs-fixer fix ./

Ошибки и качество кода

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

Самые популярные статичиские анализаторы кода:

Я покажу, как настроить и внедрить PHPStan, а вы можете добавить в проект все три по аналогии. Устанавливаем через composer сам PHPStan и несколько полезных плагинов — PHPUnit, Symfony, Doctrine.

cd /ваш/проект
composer req --dev phpstan/phpstan phpstan/phpstan-doctrine phpstan/phpstan-phpunit phpstan/phpstan-symfony

Должен создаться в корне проекта файл .phpstan.neon.dist, редактируем его:

includes:
    - vendor/phpstan/phpstan-doctrine/extension.neon
    - vendor/phpstan/phpstan-phpunit/extension.neon
    - vendor/phpstan/phpstan-phpunit/rules.neon
    - vendor/phpstan/phpstan-symfony/extension.neon
parameters:
    reportUnmatchedIgnoredErrors: false     #to avoid throwing of errors ... if no errors matching the ignored one is raised
    scanFiles:  #we need this for some twig based functions
        - '%rootDir%/../../../vendor/twig/twig/src/Extension/CoreExtension.php'
    bootstrapFiles:
        - '%rootDir%/../../../vendor/bin/.phpunit/phpunit-X.X.X/vendor/autoload.php'
    ignoreErrors:
        - message: '/^Service "[^"]+" is private.$/'
          path: '%rootDir%/../../../tests/'
    level: 0 
    symfony:
        container_xml_path: '%rootDir%/../../../var/cache/development/App_KernelDevelopmentDebugContainer.xml'

Внимательно пройдитесь по этим настройкам и укажите корректные пути. Особое внимание:

  1. bootstrapFiles — включает путь до текущего phpunit. Если его не используете, то можете закоментить.
  2. level — уровень строгости проверок от 0 до 8. 0 — самый слабый уровень, подходит для первого внедрения.

Теперь вы можете запустить проверку всего проекта (или конкретного пути) с помощью команды

./vendor/bin/phpstan analyse src tests

Советы по внедрению

Несколько советов по внедреню PHP-CS-Fixer в существующий проект с большой командой.

  1. Выберите одного ответственного, кто запустит скрипты и пофиксит весь проект у себя на локалке, а потом создаст ПР / смерджит в develop или master.
  2. Лучшее время — первое утро нового спринта. Обычно после спринта все ветки смёрджены, и это позволит залить все найденные правки в основную ветку проекта без конфликтов.
  3. В статических анализаторах используйте для начала минимальный уровень строгости проверок. У каждого анализатора для этого своя школа, читайте документацию.
  4. Первый фикс — самый критичный момент, так как правок может быть очень много. Все последующие фиксы обычно не создают ощутимых конфликтов и гит их смёрдживает самостоятельно.

Чтобы не запоминать длинные пути до скриптов, мы добавим несколько задач (tasks) в composer.json:

{
    "require": { ... },
    "require-dev": { ... },
    ...
    "scripts": {
        ...
        "csfix": "./vendor/bin/php-cs-fixer fix",
        "csfix-validate" : "./vendor/bin/php-cs-fixer fix --dry-run --diff",
        "phpstan": "./vendor/bin/phpstan analyse src tests",
        "code-quality": [
            "@phpcsfixer-validate",
            "@phpstan"
        ]

Теперь мы можем запускать проверки в упрощённом формате:

composer csfix
composer phpstan
composer code-quality

Обязательный запуск проверок перед коммитом

Внедрение этих инструментов позволяет удостовериться, что код соответствует принятому в команде стилю и не имеет очевидных опечаток и синтаксических ошибок. Однако это ещё не решает проблему забывчивости программистов и необязательности проверок.

Воспользуемся Git-хуками (git hooks) — это скрипты, которые мы можем попросить git выполнить при возникновении какого-то события: момент перед созданием коммита, момент после создания коммита, момент добавления сообщения в коммит и т. п.

Полный список git-хуков вы можете увидеть у себя в репозитории:

$ ls -al .git/hooks
-rwxr-xr-x   1 mk  staff   478 Jul 13 13:04 applypatch-msg.sample
-rwxr-xr-x   1 mk  staff   896 Jul 13 13:04 commit-msg.sample
-rwxr-xr-x   1 mk  staff  3327 Jul 13 13:04 fsmonitor-watchman.sample
-rwxr-xr-x   1 mk  staff   189 Jul 13 13:04 post-update.sample
-rwxr-xr-x   1 mk  staff   424 Jul 13 13:04 pre-applypatch.sample
-rwxr-xr-x   1 mk  staff   382 Dec  1 14:46 pre-commit
-rwxr-xr-x   1 mk  staff  1638 Jul 13 13:04 pre-commit.sample
-rwxr-xr-x   1 mk  staff   416 Jul 13 13:04 pre-merge-commit.sample
-rwxr-xr-x   1 mk  staff  1348 Jul 13 13:04 pre-push.sample
-rwxr-xr-x   1 mk  staff  4898 Jul 13 13:04 pre-rebase.sample
-rwxr-xr-x   1 mk  staff   544 Jul 13 13:04 pre-receive.sample
-rwxr-xr-x   1 mk  staff  1492 Jul 13 13:04 prepare-commit-msg.sample
-rwxr-xr-x   1 mk  staff  3610 Jul 13 13:04 update.sample

Создадим скрипт, который будет запускать проверки каждый раз перед попыткой создать коммит.

vim .git/hooks/pre-commit

Добавляем внутрь файла:

#!/bin/sh
export PATH=/usr/local/bin:$PATH
# Если вы используете docker-compose (рекомендуется), то добавьте
export COMPOSE_INTERACTIVE_NO_CLI=1

if [ -t 1 ]; then
    # If we're in a terminal, redirect stdout and stderr to /dev/tty and
    # read stdin from /dev/tty. Allow interactive mode for CaptainHook.
    exec >/dev/tty 2>/dev/tty </dev/tty
fi

errors=0

composer code-quality
# или, если вы используете docker-compose (рекомендуется), то
docker-compose exec -T web php bin/composer code-quality

if [ "$?" -ne 0 ]; then
    errors=1
fi

if [ "$errors" -eq 1 ]; then
    echo "Errors detected!"
    exit 1
fi

Теперь можете попробовать сделать ошибку в .php файле и создать коммит. Git должен ругнуться:

Устанавливаем git-hook автоматически

Финальный шаг — добавить git-hook в .git/hooks/ папку при запуске composer. Тогда ни один разработчик не сможет пропустить запуск проверок по невнимательности. Для этого добавим в composer.json такую строку:

{
    ...,
    "scripts": {
        "post-autoload-dump": "mkdir -p .git/hooks && cp config/pre-commit .git/hooks/pre-commit",
        ...
    }
}

Итог

  1. Мы добавили в проект PHPCsFixer для код-стайла и PHPStan для поиска ошибок и опечаток.
  2. Запускаем их при каждой попытке создать коммит.
  3. И всё это начинает работать автоматически после первого же composer install.

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

Проблема

Под root-пользователем работать небезопасно, равно как и делать весь проект доступным www-data.
Кроме того, во многих веб-приложениях пользователи имеют возможность загружать свои файлы. И очень часто с такими файлами возникают конфликты, так как пишутся они под www-data:www-data, а деплоим под другим пользователем. Даже если деплоить под root, то скорее всего права на папку перепишутся и www-data потеряет доступ к нужным файлам.

Решение

Создать нового пользователя deploy с правами на коннект к серверу по ssh, доступом только к папке с проектом и возможностью изменять файлы в ./public/uploads и ./var.

Создаём на сервере пользователя deploy из-под root:

ssh root@вашсервер
useradd --create-home -s /bin/bash deploy

Настроим доступ по ssh через ключи

mkdir /home/deploy/.ssh
touch /home/deploy/.ssh/authorized_keys

Вставьте содержимое одного из публичного ключа своего локального пользователя в файл authorized_keys и сохраните. Вывести публичный ключ локально можно командой: cat ~/.ssh/id_rsa.pub (название ключа id_rsa.pub у вас может отличаться).

vim /home/deploy/.ssh/authorized_keys

Меняем права на более строгие

chown -R deploy:deploy /home/deploy
chmod 600 /home/deploy/.ssh/authorized_keys

Определим пользователя нашего веб-сервера (в примере ниже это www-data)

ps axo user,comm | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\  -f1
> www-data

Добавляем пользователя deploy в группу www-data (группа веб-сервера)

usermod -a -G www-data deploy

Выставляем права на папку проекта

chown -R deploy:deploy /var/www/project
chmod -R 0775 /var/www/project

Проверим, есть ли setfacl в системе setfacl -h и установим, если его нет. Команда для Ubuntu:

sudo apt-get install acl

Выдадим права на папки с кэшем, логами и загруженными пользовательскими файлами

sudo setfacl -dR -m u:www-data:rwX -m u:deploy:rwX /var/www/project/var /var/www/project/public/uploads
sudo setfacl -R -m u:www-data:rwX -m u:deploy:rwX /var/www/project/var /var/www/project/public/uploads

Готово.

Для самого деплоймента я обычно использую Deployer c параметром writable_mode=acl.

Фавиконки для сайтов

Такая мелочь, как иконка сайта в табе браузера, не является критичной, но тем не менее влият на внешний вид вашего сайта и на его респектабельность.

Проблема

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

Решение

https://realfavicongenerator.net/ — создаёт все эти варианты иконки по одному файлу и генерирует HTML.

Наконец-то, роботы трудятся на благо человека!

Как прокачать Vim за 1 минуту

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

Настройка vim происходит в файле ~/.vimrc. Его может не быть, это нормально, тогда нужно создать.

  1. Открываем ~/.vimrc
$ vim ~/.vimrc
  1. Добавляем в файл следующее содержимое и сохраняем (команда «:wq»):
set ttyfast
set showmode
set showcmd
set title
set hidden
set ffs=unix,dos,mac

" Показывать нумерацию строк
set number

" Чтобы не было проблем с swp-файлами, которые создаются во время редактирования
set nobackup
set nowritebackup
set nowb
set noswapfile

" Глубина истории
set undolevels=1000

syntax on
" Цветовая схема
set t_Co=256

" monokai не идёт по умолчанию, но мы его установим чуть позже
colorscheme monokai

" Рисовать вертикальную линию для отображения границы в 120 символов — строки длинее хуже читаются
set colorcolumn=120
highlight ColorColumn ctermbg=238 guibg=#232728

" Настройка табов
set expandtab
set tabstop=4
set shiftwidth=4

" Отображать скрытые символы, табы и висящие пробелы
set list
set listchars=tab:→\ ,trail:·,nbsp:·
  1. Я использую тёмную тему monokai. Её нет среди тем по умолчанию, но установить её несложно:

ls —l /usr/share/vim/vim*/colors покажет все предустановленные в системе темы

$ mkdir -p ~/.vim/colors
$ curl -o ~/.vim/colors/monokai.vim https://raw.githubusercontent.com/sickill/vim-monokai/master/colors/monokai.vim

Имя этого файла с темой нужно указать в ~/.vimrc в строке

colorscheme <monokai>
Ранее Ctrl + ↓