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

Потом началось время статических генераторов. Markdown, картинки. Генерация сайта на ноутбуке, выкладывание rsync’ом статей и картинок. Скорость доступа к страницам потрясающая. Билд сайта — не очень. Потому что всё на ruby и смена версии или переустановка приводила к ошибкам и невозможности что-либо опубликовать.

История домашнего “Continuous Delivery”:

  • итерация 1, май 2015. Github, сборка на Jenkins в контейнере, публикация по rsync
  • итерация 2, июль 2015. Github, сборка на Travis и публикация в S3
  • итерация 3, май 2016. Github, webhook’и и сборка в контейнерах на web-сервере

Цена на Travis с приватными репозиториями для hobbyist’а неразумная (старт $69 в месяц), в паблик выносить репозиторий сайта почему-то не хочу (причина простая — для себя можно коммит обозвать и “Fix issue in the ci file”, а вот в паблике уже тянет на “gitlab-ci: Use GIT_STRATEGY clone due the strange errors with fetch”).

Пытался по статье Дениса Евсюкова использовать Netlify — сайт строится замечательно, а вот с картинками в LFS не сложилось, он не поддерживает LFS. Тогда это было критично, сейчас же я вопрос решил, но Netlify мне неактуален.

К тому же захотелось поставить свой сервер Gitlab и поэкспериментировать с Gitlab CI (по профессиональной деятельности я его использую, но захотелось “для себя”). Памяти под сервер нужно 4 GB, на Digital Ocean это стоит $40 в месяц. Что чересчур. Вспомнил про когда-то горячо любимый Linode. Оказалось, что у меня там $40 реферальных лежит. Там сервер на 4 GB стоит $20. Неплохо!

Я думаю, что вы все прекрасно знаете Linode и его отличное качество. В подтверждение приведу небольшую историю. С год назад мы перенесли с Digital Ocean на Linode один “широко известный в узких кругах” сайт. Цена уменьшилась в два раза, а скорость увеличилась как минимум на 30%, субъективно стало летать.

Поставил Gitlab CE, запустил CI runner, настроил ежедневный бекап в S3. Перенёс все приватные репозитории с Github. В процессе понял, что много кода в публичных устарело, поэтому удалил и их. Отказался от подписки. $7 в месяц сэкономил.

Пользовался Gitlab недели две — всё летало. Потом решил, что вполне могу перейти от self-hosted Gitlab CE на Gitlab.com c фичами EE. Бесплатно. Было опасение — когда-то я съехал с gitlab.com из-за диких тормозов, порой не то что открыть сайт нельзя было из-за 500-х, но и репозитории обновить или стянуть по ssh нельзя было (это не было связано с эпической историей восстановления gitlab.com). Но пока копировал данные, то такого уже не было. Решил дать шанс.

В процессе перевёл блог на Jekyll 3. Добавил CI, всё идеально.

Получился такой .gitlab-ci.yml для блога:

image: jekyll/builder
variables:
  GIT_STRATEGY: clone

stages:
  - build
  - deploy

build:
  stage: build
  script:
    - jekyll build
  artifacts:
    expire_in: 1 month
    paths:
      - _site
  only:
    - master

deploy_lon:
  stage: deploy

  before_script:
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'

  environment:
    name: lon
    url: https://ctrld.me
  script:
    - echo "Deploy to lon"
    - ls -al
    - rsync -az -e ssh --delete _site/ deploy@ctrld.me:/srv/j3.ctrld.me/
  only:
    - master

Переменные SSH_PRIVATE_KEY и SSH_SERVER_HOSTKEYS прописаны в Pipeline settings репозитория.

Приятная вещь — артефакты. Сайт билдится на стадии build, результат пакуется в zip. На стадии deploy архив стаскивается и раскручивается. Что очень нравится — можно сделать rollback к любому предыдущему деплою. Например, когда что-то сильно сломалось, а ты на “ходу” с телефоном.

Для картинок всё хуже. Я их храню тоже в git, конечно же с LFS. Клонирование такого репозитория на 1.5 GB занимает кучу времени. Поэтому сделал сильно проще. Сам репозиторий не клонируется (GIT_STRATEGY: none), таск деплоя заходит на web-сервер и делает git pull в репозитории с картинками. Почти мгновенно всё отрабатывает.

# Don't clone repository, run git pull on remote side
variables:
  GIT_STRATEGY: none

stages:
  - deploy

deploy_lon:
  image: jekyll/builder
  stage: deploy

  before_script:
    # https://docs.gitlab.com/ee/ci/ssh_keys/README.html
    - eval $(ssh-agent -s)
    - ssh-add <(echo "$SSH_PRIVATE_KEY")
    - mkdir -p ~/.ssh
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
    - '[[ -f /.dockerenv ]] && echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts'

  environment:
    name: lon
    url: https://ctrld.me
  script:
    - echo "Deploy to lon"
    - ls -al
    - 'echo "cd /srv/cdn && git reset --hard && git pull" | ssh -T deploy@ctrld.me'
  only:
    - master

В этой схеме не нужно запускать сервисы для webhook’ов на web-сервере. Нужно лишь сделать доступ по ssh с авторизацией по ключам.

Всё работает и мне это нравится (3 минуты 35 секунд на сайт с 650 заметками и 25 секунд на картинки). Я не особо собираюсь писать “с ног” на телефоне в блог, но потенциально и на iOS можно написать заметку, запушить её в репозиторий и дальше всё соберётся автоматом.

P.S. Не люблю статьи в блогах типа “как я пишу статьи в блоге”. Какая-то нездоровая рекурсия. Однако тема DevOps может быть интересной, вот и написал. Может распишусь. Хочется сделать серию статей об использовании ledger-cli/hledger.