С блогами у меня всегда что-то не получалось — то лень, то страшный, то неудобный. Я пробовал и ЖЖ, и тумблер, и даже blogspot. Потом наткнулся на octopress, который сразу понравился своим минимализмом. Он красив, шустр, можно размещать на халявном GitHub Pages. Но он давно не обновлялся и немного загонен. Не так сильно, как его предок Jekyll, но все же кодерских действий в нем, как в обычном проекте.
Так что с блогами у меня не вязалось. Но сохранять описания своих действий все же хочется, поэтому я снова вдарился в поиски. В критериях были простота, удобство и поддержка markdown. Тут-то я наткнулся на Ghost. Поднимается он легко, базу особо не требует. А тут еще нашел генератор статики из него, чтобы можно было заливать сайт на гитхаб. Он мне так понравился, что теперь мы даже используем его в админском отделе в качестве хранилища документации. Множество википедий у нас не шло так же, как у меня блог сервисы. Ниже опишу основные моменты, с которыми я имел дело при настройке.
Установка
На машине достаточно установленного nodejs (и MySQL\PostgreSQL, если нужна тяжелая база)
- качаем архив с движком с https://ghost.org/download/
- разархивируем его, куда надо
- ставим нужные модули
npm install --production - запускаем дев окружение
npm start - в браузере открываем http://localhost:2368
- для доступа в админку ломимся в http://localhost:2368/ghost
- profit!
vitaly@Vitalys-MacBook-Pro /tmp/blog $ wget https://ghost.org/zip/ghost-0.5.10.zip
vitaly@Vitalys-MacBook-Pro /tmp/blog $ unzip ghost-0.5.10.zip -d ghost
vitaly@Vitalys-MacBook-Pro /tmp/blog $ cd ghost
vitaly@Vitalys-MacBook-Pro /tmp/blog/ghost $ npm install --production
npm WARN engine html-to-text@1.2.0: wanted: {"node":">= 0.8.0 <0.12"} (current: {"node":"0.12.0","npm":"2.5.1"})
> sqlite3@3.0.5 install /private/tmp/blog/ghost/node_modules/sqlite3
> node-pre-gyp install --fallback-to-build
[... много текста ...]
sqlite3@3.0.5 node_modules/sqlite3
└── nan@1.6.2
vitaly@Vitalys-MacBook-Pro /tmp/blog/ghost $ npm start
> ghost@0.5.10 start /private/tmp/blog/ghost
> node index
Migrations: Database initialisation required for version 003
Migrations: Creating tables...
Migrations: Creating table: posts
Migrations: Creating table: users
Migrations: Creating table: roles
Migrations: Creating table: roles_users
Migrations: Creating table: permissions
Migrations: Creating table: permissions_users
Migrations: Creating table: permissions_roles
Migrations: Creating table: permissions_apps
Migrations: Creating table: settings
Migrations: Creating table: tags
Migrations: Creating table: posts_tags
Migrations: Creating table: apps
Migrations: Creating table: app_settings
Migrations: Creating table: app_fields
Migrations: Creating table: clients
Migrations: Creating table: accesstokens
Migrations: Creating table: refreshtokens
Migrations: Populating fixtures
Migrations: Populating permissions
Migrations: Creating owner
Migrations: Populating default settings
Migrations: Complete
Ghost is running in development...
Listening on 127.0.0.1:2368
Url configured as: http://localhost:2368/
Ctrl+C to shut down
Загрузка на GitHub Pages
Сперва я хотел уже заказывать сервер на DigitalOcean, но черт меня дернул загуглить размещение блога ghost на гитхабе. И я нашел небольшой хак на питоне Buster, который парсит сайт и генерирует статические страниы для загрузки на GitHub Pages. Для бастера нужны wget и git.
- Устанавливаем бастера
pip install buster - Создаем директорию для репозитория блога
- На гитхабе создаем репозиторий для блога
- Подготваливаем локальный репозиторий бастера
buster setup --gh-repo=<git_repo> - Генерируем статику
buster generate --domain=localhost:2368 - Заливаем на гитхаб
buster deploy
vitaly@Vitalys-MacBook-Pro ~ $ mkdir /tmp/blog-git
vitaly@Vitalys-MacBook-Pro ~ $ cd /tmp/blog-git
vitaly@Vitalys-MacBook-Pro /tmp/blog-git $ buster setup --gh-repo="git@github.com:dragolabs/dragolabs.github.io.git"
vitaly@Vitalys-MacBook-Pro /tmp/blog-git $ buster generate --domain=http://127.0.0.1:2368
-2015-03-25 12:17:50-- http://127.0.0.1:2368/
Connecting to 127.0.0.1:2368... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4663 (4.6K) [text/html]
Saving to: '/private/tmp/2/static/index.html'
[... много текста ...]
fixing links in /private/tmp/2/static/rss/index.rss
vitaly@Vitalys-MacBook-Pro /tmp/blog-git $ buster deploy
Подсветка синтаксиса
Есть много вариантов включения подсветки кода. Подсветка есть в некоторых темах, можно подключить скрипт от гугла. Мне больше всего приглянулись два варианта.
Highlights.js
https://highlightjs.org/
Написан авторами хабра, знает много языков, имеет много тем, владеет функцией автоопределения языка в блоке кода. Сборка с самыми популярными языками доступна к прямому подключению, ибо выложена на CDN. Его я выбрал для админского хранилища доков, как раз за автоопределение.
Prism.js
http://prismjs.com/
Легкий, 6 тем, чуть меньше языков, используется кучей популярных проектов. Для подключения надо сгенерировать и залить к себе. В отличие от предыдущего кандидата, имеет подключаемые модули для нумерации и выделения строк, выделения ссылок, подстветки символов итд. Его я выбрал для себя, т.к. его тема мне более симпатична.
Подключаются оба варианта одинаково. Если не использовать готовый скрипт с CDN, генерируем и скачиваем файлы, и кидаем их в _blog_/content/themes/_theme_name_/assets/css и _blog_/content/themes/_theme_name_/assets/js соответственно. В $theme_name теме, в default.hbs в секции {{! Styles'n'Scripts }} дописываем подключение css и js. Многие рекомендуют подключать js в самом низу страницы, но у меня и вверху все прекрасно работает.
{{! Styles'n'Scripts }}
<link rel="stylesheet" type="text/css" href="{{asset "css/screen.css"}}" />
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:700,400" />
<link rel="stylesheet" type="text/css" href="{{asset "css/prism.css"}}" />
<script type="text/javascript" src="{{asset "js/prism.js"}}"></script>
{{! Ghost outputs important style and meta data with this tag }}
В случае highlights.js для автоопределения надо будет подключить еще один js скрипт.
{{! Styles'n'Scripts }}
<link rel="stylesheet" type="text/css" href="{{asset "css/screen.css"}}" />
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans:700,400" />
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/styles/monokai_sublime.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.4/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
{{! Ghost outputs important style and meta data with this tag }}
Комментарии Disqus
Для подключения комментариев достаточно зарегистрироваться в Disqus и вставить кусок кода, как указано в их документации.
Поиск
Для статичного сайта поиск актуален больше с помощью гугла, а вот во внутренней документации локальный поиск просто необходим. Подключать его не столько трудно, сколько геморно его более-менее красиво вставить.
- Топаем на https://github.com/jamalneufeld/ghostHunter и качаем архив с полезным js скриптом
- Минимизированный js скидываем в уже знакомый каталог
_blog_/content/themes/_theme_name_/assets/js - В $theme_name в default.hbs в перед
</body>подлючаем наш js. - И в понравившемся нам месте размещаем поле и кнопку поиска, и секцию для вывода результатов.
<form>
<input id="search-field" />
<input type="submit" value="search">
</form>
<section id="results"></section>
$("#search-field").ghostHunter({
results : "#results"
});
В принципе, на этом можно остановиться, но общий вид меня удручал, так что я убрал вообще кнопку поиска, облагородил поле ввода и перенес поле и вывод результата наверх. И добавил эти поля во все шаблоны (пост, тэг, индекс) вместо использования одного только default, где можно вставить поле либо над лого, либо ниже футера.
default.hbs
{{! The main JavaScript file for Casper }}
<script type="text/javascript" src="{{asset "js/jquery.fitvids.js"}}"></script>
<script type="text/javascript" src="{{asset "js/index.js"}}"></script>
<script src="{{asset "js/jquery.ghostHunter.min.js"}}"></script>
<script>
$("#search-field").ghostHunter({
results : "#results"
});
</script>
</body>
index.hbs
</header>
<form class="site-search">
<input type="search" id="search-field" placeholder="Search" class="search-box" />
</form>
<section id="results" class="search-results"></section>
{{! The main content area on the homepage }}
screen.css
.search-box{
width: 250px;
float: right;
display: block;
font-size: 1.8rem;
margin-right: 10px;
}
.search-results{
position: relative;
display: block;
margin: 0 auto;
text-align: center;
width: 80%;
background: #eee;
max-width: 870px;
}
Запуск через forever
Запускать сервер через npm start хорошо, когда все ограничивается локальным компом. На сервере же управление процессом лучше доверить какому-нибудь демону. Вариантов масса: написать init скрипт, настроить runit, supervisord, forever, pm2. Я решил пока не заморачиваться, и использовать forever для хранилища доков. Для боевого сервера лучше использовать pm2, т.к. он умеет и генерить init скрипты, и мониторить процессы и что только.
- ставим forever
npm install forever -g - под юзером проекта в проектном каталоге запускаем сервер
sudo -u ghost NODE_ENV=production forever start index.js - чтобы перезапустить ghost, можно сделать так
sudo -u ghost forever restartall - чтобы блог запустился после рестарта системы, можно сделать init скрипт или дописать в
/etc/rc.localкоманду запуска сервера
Buster
Для публикации блога на GitHUb Pages можно воспользоваться прекрасным питоновским приложением, которое распарсит локальный сайт, закоммитит в репозиторий и запушит на сервер.
vitaly@Vitalys-MacBook-Pro ~$ sudo easy_install pip
vitaly@Vitalys-MacBook-Pro ~$ sudo pip install buster
Далее можно использовать следующие команды:
# Создание нового репозитория для блога
vitaly@Vitalys-MacBook-Pro ~$ buster setup
# Генерируем статичную версию сайта
vitaly@Vitalys-MacBook-Pro ~$ buster generate --domain=http://127.0.0.1:2368
# Пушим изменения на гит-сервер
vitaly@Vitalys-MacBook-Pro ~$ buster deploy
Но, оказывается, buster не умеет пока сливать sitemap файлы. В итоге, на просторах интернета я наткнулся на скриптик для генерации и заливки сайта. Взял отсюда: http://joshgerdes.com/host-a-static-ghost-blog-on-github/
#!/bin/bash
# Generate static files with buster
buster generate --domain=http://127.0.0.1:2368
# Copy sitemap files
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap.xsl
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap.xml
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap-pages.xml
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap-posts.xml
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap-authors.xml
wget --convert-links --page-requisites --no-parent --directory-prefix static --no-host-directories --restrict-file-name=unix http://127.0.0.1:2368/sitemap-tags.xml
# Replace urls that were missed by buster
find static/* -name robots.txt -type f -exec sed -i '' 's#http://blog.dragolabs.org#http://blog.dragolabs.org#g' {} \;
find static/* -name *.xsl -type f -exec sed -i '' 's#http://blog.dragolabs.org#http://blog.dragolabs.org#g' {} \;
find static/* -name *.xml -type f -exec sed -i '' 's#loc>http://blog.dragolabs.org#loc>http://blog.dragolabs.org#g' {} \;
find static/* -name *.html -type f -exec sed -i '' 's#u=http://blog.dragolabs.org#u=http://blog.dragolabs.org#g' {} \;
find static/* -name *.html -type f -exec sed -i '' 's#url=http://blog.dragolabs.org#url=http://blog.dragolabs.org#g' {} \;
find static/* -name *.html -type f -exec sed -i '' 's#href="http://blog.dragolabs.org#href="http://blog.dragolabs.org#g' {} \;
find static/* -name *.html -type f -exec sed -i '' 's#src="http://blog.dragolabs.org#src="http://blog.dragolabs.org#g' {} \;
find static/* -name *.html -type f -exec sed -i '' 's#link>http://blog.dragolabs.org#link>http://blog.dragolabs.org#g' {} \;
# Add CNAME file for github pages
buster add-domain blog.dragolabs.org
buster deploy