Заметки в категории How To

Собираем логи из docker в GrayLog

logspout

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

Классический ELK я не очень люблю, а потому стал искать варианты, которые мне бы понравились. В итоге, пришел к GrayLog.

Оставался вопрос сборщика логов, для отправки их в GrayLog, который сложит их в ElasticSearch.

Перебрал кучку малую и остановился на Logspout. Он умеет отправлять логи в syslog, GELF и, что не маловажно, он умеет multiline logs. Т.е. Tracebacks будут не построчно, а целиком, как положено.

Ну что ж, поднимаем.
Читать далее...

Копируем S3 баккет между AWS аккаунтами

S3

Предположим, что нам надо скопировать данные из баккета в одном аккаунте, в баккет в другом аккаунте, да еще и в другом регионе.

Что нам понадобится

  • Два AWS аккаунта (один для исходного баккета, второй для баккета назначения)
  • IAM пользователь в аккаунте с баккетом, куда мы будем копировать данные (тут есть документация, как создать IAM пользователя в аккаунте)
  • Настроенная утилита aws-cli на локальной машине с ключами ранее созданного пользователя (документация по утилите)

Шаг 1: Получаем номер аккаунта

Заходим в аккаунт назначения. Переходим в SupportSupport center и копируем номер аккаунта.

Шаг 2: Настраиваем исходный S3 баккет

Заходим в аккаунт-источник. Создаем баккет источник (если его еще не было, то что вы тут делаете? ;) документация как создать баккет). Аттачим полиси, которое представлено ниже (как приаттачить полиси). Если вы только создали баккет, то залейте несколько файлов туда для теста.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "DelegateS3Access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::DESTINATION_BUCKET_ACCOUNT_NUMBER:root"
            },
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::SOURCE_BUCKET_NAME/*",
                "arn:aws:s3:::SOURCE_BUCKET_NAME"
            ]
        }
    ]
}

Шаг 3: Настраиваем баккет назначения

Заходим в аккаунт назначения. Создаем баккет, куда будем копировать данные.

Шаг 4: Аттачим полиси к созданному пользователю

Аттачим к созданному пользователю полиси, которое представлено ниже (как приаттачить полиси пользователю).

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::SOURCE_BUCKET_NAME",
                "arn:aws:s3:::SOURCE_BUCKET_NAME/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::DESTINATION_BUCKET_NAME",
                "arn:aws:s3:::DESTINATION_BUCKET_NAME/*"
            ]
        }
    ]
}

Шаг 5: Синхронизируем данные

Если вы сделали все шаги, описанные выше, то можно начать синхронизацию.

aws s3 sync s3://SOURCE-BUCKET-NAME s3://DESTINATION-BUCKET-NAME --source-region SOURCE-REGION-NAME --region DESTINATION-REGION-NAME

Добавляем memcached в стэк Wordpress by Bitnami

wordpress

Понадобилось мне тут в проекте добавить поддержку Memcached в Wordpress, развернутый на Amazon. Кто не в курсе, то там используется предустановка от Bitnami. Поскольку в этом стэке используется не системный PHP, а кастомный, то и добавить туда модуль PHP не тривиальная задача. При попытке использовать доку от Bitnami я получил кучу ошибок и перерыл кучу форумов, чтоб их решить. В результате все мои изыскания вылились в простой скрипт, который все ставит и перезапускает php-fpm.

export LIBMEMCACHED_VERSION='1.0.18'
export PHPMEMCACHED_VERSION='2.2.0'

# Install dependencies

sudo apt update
sudo apt install -y memcached
sudo apt install -y build-essential libtool autoconf unzip wget git pkg-config

# Create folder

sudo mkdir /opt/bitnami/common
sudo chmod 777 /opt/bitnami/common/

# Setup libmemcached

cd /tmp
wget https://launchpad.net/libmemcached/1.0/${LIBMEMCACHED_VERSION}/+download/libmemcached-${LIBMEMCACHED_VERSION}.tar.gz
tar -zxf libmemcached-${LIBMEMCACHED_VERSION}.tar.gz
cd libmemcached-${LIBMEMCACHED_VERSION}
./configure --prefix=/opt/bitnami/common
make
sudo make install

# Setup php extension

cd /tmp
export PHP_AUTOCONF=/usr/bin/autoconf
export PHP_PREFIX=/opt/bitnami/php
wget http://pecl.php.net/get/memcached-${PHPMEMCACHED_VERSION}.tgz
tar -xzf memcached-${PHPMEMCACHED_VERSION}.tgz
cd memcached-${PHPMEMCACHED_VERSION}
/opt/bitnami/php/bin/phpize
./configure --enable-memcached --with-zlib-dir=/opt/bitnami/common --with-libmemcached-dir=/opt/bitnami/common --with-php-config=/opt/bitnami/php/bin/php-config --disable-memcached-sasl
make
sudo make install
echo 'extension=memcached.so' | sudo tee -a /opt/bitnami/php/etc/php.ini

# Restart php-fpm

sudo /opt/bitnami/ctlscript.sh restart php-fpm

iRedMail и “+” в адресе

iredmail

Я как-то давно отказался от услуг Google в плане почты и переехал на свой сервер. Одно время пользовался решением в docker’e, но там было не все гладко. В результате поднял свой сервер и поставил туда iRedMail. Это оказалось сильно дешевле, чем платить сторонним сервисам.

Но там мне не хватало одной очень удобной возможности — добавление символа “+” после имени пользователя, чтоб была возможность фильтрации по получателю. Это очень удобно, т.к. для каждого сервиса можно завести свой индивидуальный почтовый ящик. Что, в свою очередь, помогает идентифицировать утечку. ;)

Итак, что надо сделать, чтоб получать почту в свой ящик, отправленную на адреса вида “[email protected]”.

Открываем файл /etc/postfix/mysql/virtual_alias_maps.cf и меняем там одну строку.

Было:

query       = SELECT ... WHERE forwardings.address='%s' AND ...

Стало:

query       = SELECT ... WHERE forwardings.address=CONCAT(SUBSTRING_INDEX('%u', '+', 1), '@%d') AND ...

Перезагружаем Postfix и наслаждаемся. :)

Merge git-crypted files

git-crypt

Давно искал как получить возможность мерджить файлы, которые зашифрованы git-crypt.

В результате нашел вот такое решение.

Во-первых, добавьте в .gitattributes параметр merge=git-crypt для всех файлов, управляемых git-crypt:

crypt/** filter=git-crypt diff=git-crypt merge=git-crypt

затем добавьте в конец файла .git/config следующее:

[merge "git-crypt"]
    name = A custom merge driver used to merge git-crypted files.
    driver = ./my-merge-tool.sh %O %A %B
    recursive = binary

и, наконец, создать файл в корне repo my-merge-tool.sh содержащий:

ancestor_decrypted="$1__decrypt"
current_decrypted="$2__decrypt"
other_decrypted="$3__decrypt"
echo ""
echo "###########################"
echo "# Git crypt driver called #"
echo "###########################"
echo ""

echo "Decrypting ancestor file..."
cat $1 | git-crypt smudge > "${ancestor_decrypted}"
echo "Decrypting current file..."
cat $2 | git-crypt smudge > "${current_decrypted}"
echo "Decrypting other file..."
cat $3 | git-crypt smudge > "${other_decrypted}"
echo ""

echo "Merging ..."
git merge-file -L "current branch" -L "ancestor branch" -L "other branch" "${current_decrypted}" "${ancestor_decrypted}" "${other_decrypted}"
exit_code=$?
cat "${current_decrypted}" | git-crypt clean > $2

echo "Removing temporary files..."
rm "${other_decrypted}" "${ancestor_decrypted}" "${current_decrypted}"

if [ "$exit_code" -eq "0" ]
then
    echo "@@@ No conflict!"
else
    echo "@@@ You need to solve some conflicts..."
fi

exit $exit_code

и убедитесь, что он выполним:

chmod +x my-merge-tool.sh

Это все, теперь вы можете делать merge, cherry-pick, использовать свой любимый mergetool, как обычно!

Заставляем GitX подписывать коммиты

Я часто использую GitX, как вариант замены коммандной строки, т.к. в нем удобно добавлять несколько коммитов один за одним, выбирая разные файлы или группы файлов. Но вот незадача, он не умеет ставить на commit GPG подпись. Т.е. получается в истории коммитов часть подписана, а часть нет. Некрасиво.

Чтож, научить его это делать несложно, если написать простой wrapper.

Для начала в .gitconfig добавляем такие строки:

[commit]
  gpgsign = true

Теперь создаем враппер по пути что-то типа ~/bin/gitx-signed-commit с содержимым:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env bash

args=("[email protected]")

if [[ "$1" = "commit-tree" ]] && [[ "$(git config --get commit.gpgsign)" = "true" ]]; then
  args=("commit-tree" "-S" "${args[@]:1}")
fi

git "${args[@]}"

Даем права на запуск:

$ chmod 755 ~/bin/gitx-signed-commit

Осталось подключить в GitX. Для этого идем в настройки, выбираем вкладку General, тыкаем на Git Executable и выбираем наш скрипт.

Все. С этого момента все коммиты будут подписываться корректно.

Очистка смердженных веток

По роду своей деятельности приходится создавать довольно много веток в репозитории с кодом инфраструктуры и поддерживать все это во вменяемом состоянии становится все сложнее.

Пришлось что-то придумывать.

Нет ничего лучше для этой цели, как алиасы в git. Итак, для начала разберем, что надо делать, а потом напишем алиас.

Первое - это забираем и подчищаем ветки из remote:

$ git fetch -p

Теперь можно посмотреть уже смердженные ветки:

$ git branch --merged

В результате мы получим все смердженные ветки, но в списке будет и master. Надо будет его отфильтровать.

Теперь можно удалить эти смердженные ветки:

$ git branch -d branch_name

Собираем это все в алиас. В ~/.gitconfig добавляем строку в секцию [alias]:

[alias]
    cleanup = "!git checkout master && git fetch -p && git branch --merged | grep -v '* ' | xargs -I {} git branch -d {}"

просто используем:

$ git cleanup

В результате получаем чистый репозиторий: все смердженные ветки будут вычищены полностью.

Восстановление пароля root для MySQL

Если вы забыли пароль для пользователя root в базе MySQL/MariaDB/PerconaDB, то вам понадобиться несколько простых действий, чтоб его сменить:

  • Останавливаем MySQL:
sudo service mysql stop
  • Создаем текстовый файл /tmp/init.sql:
ALTER USER 'root'@'localhost' IDENTIFIED BY 'MyNewPass';
  • Запускаем сервер:
sudo mysqld_safe --skip-grant-tables
  • Открываем второй терминал, заходим в mysql и меняем пароль пользователю root:
mysql -u root mysql
UPDATE mysql.user SET authentication_string = PASSWORD('MyNewPass') WHERE User = 'root' AND Host = 'localhost';
FLUSH PRIVILEGES;
exit;

Осталось убить процесс mysqld. Для этого в первом терминале нажимаем Ctrl+C и стартуем:

sudo service mysql start

How To: Как создать MySQL пользователя с минимальными правами для бекапа

Использовать для бекапа пользователя root плохая мысль. Создадим пользователя с минимальными правами:

CREATE USER 'botbackup'@'localhost' IDENTIFIED BY 'password';
GRANT SELECT, SHOW VIEW, RELOAD, REPLICATION CLIENT, EVENT, TRIGGER ON *.* TO 'botbackup'@'localhost';
GRANT LOCK TABLES ON *.* TO 'botbackup'@'localhost';

How To: 16 практических примеров команды ls

Команда ls применяется для просмотра списка файлов в каталоге. Хотя, если вы используете Unix-like систему, то вы это уже знаете не хуже меня.

Но все ли вы знаете об этой прекрасной команде? Может быть вы используете ее не до конца?

1. Показать все файлы в каталоге

Классический вариант команды ls - это:

ls -a

Вывод покажет все файлы и каталоги в текущем каталоге, включая скрытые. В том числе и служебные '.' и '..'

2. Скрыть служебные каталоги '.' и '..'

ls -A

3. Отображение файлов и каталого в обратном порядке

По умолчанию, ls возвращает список файлов и каталогов в алфавитном порядке. Если необходимо вернуть список в обратном порядке:

ls -r

4. Сортируем файлы по расширению

Это тоже можно легко сделать:

ls -X

Читать далее...