Gollum搭建实战篇
感觉以后可以出个实战篇系列,毕竟只有自己动手操作过,感受才会比较深,解决方法不说最好,但至少是在当时管用的:)
闲话少说,今天带来的是一个比较小资的wiki管理系统--Gollum,为啥叫小资呢,因为我感觉这个系统采用的极简风格非常具有小资情调,而且要能够玩转这个系统,你也必须是一个开发者,所以这个系统并不适合所有人,但对于有追求的小资来说,却是再好不过的了。
首先上一张最终的效果图,如果你感觉不是你喜欢的风格,那么接下来就可以不用看了:)
效果图
简单的标题,功能强大的搜索框(支持wiki内的全文搜索哦),加上两个必不可少的功能按钮,这就是全部了。刚开始很多人对这种风格还不是很适应,但用一段时间,估计大家就会喜欢上,毕竟极简风现在很流行啊!
安装准备
Gollum是使用ruby开发的,要求ruby的版本在1.9以上,所以如果你是老版本的ruby,那就需要升级咯,这里给出一个yum安装高版本ruby的方法。
首先安装yum源
yum install centos-release-scl-rh
安装指定版本的ruby
yum install rh-ruby24 -y
使用scl安装的软件缺省是不在path路径里的,需要手动激活
scl enable rh-ruby24 bash
当然为了避免麻烦,你也可以找到enable
脚本,然后把其中的内容复制到你的.bashrc
中,通常enable
脚本的路径为
/opt/rh/rh-ruby24/enable
这时你可以看看ruby的版本号
ruby -v
因为gollum是需要编译安装的,因此你还需要安装ruby-devel
、rubygems
包
yum install rh-ruby24-ruby-devel rh-ruby24-rubygems -y
如果你之前没有安装过其它需要编译的软件包,那么大概率你还需要安装下面几个包
yum install libicu libicu-devel zlib zlib-devel -y
这时候你可以执行以下gem
看看版本号(这是一个安装管理工具,和yum
类似,不过管理的对象是用ruby开发的程序)
gem -v
如果到这里一切顺利,那么恭喜你,真正困难的路终于要开始了!
中国特色
一切需要从国外源下载安装的软件都会有这个类似的环节,那就是国外源实在是太太太慢了,只能换成国内的源,从这一点来看,这几年阿里和淘宝做得不错,百度就不行了,但今天这个gem源却不是这哥仨提供的,原来淘宝有个源,但现在好像已经不维护了。下面就是换源操作
# 添加国内源
gem sources -a http://gems.ruby-china.com/
# 删除官方源
gem sources -r http://rubygems.org/
# 查看当前源
gem sources -l
该国内源到本文发布之时可用(只能这么说了)
安装Gollum
一切就绪,怀着激动的心情按下回车键吧
gem install gollum
真的就这么简单,然后你就可以出去走走,呼吸一下新鲜空气,喝杯茶,然后再回来看结果。
写在后面
经过休息,回来发现已经安装完毕了,一共耗时不到1个小时,感觉这也不像之前说得这么复杂啊。最多是和一般wiki不一样的,gollum需要一个git目录才能使用
# 创建一个空目录
mkdir wiki
# 进入目录
cd wiki
# 初始化为git项目目录
git init
# 启动gollum
gollum
然后打开浏览器,访问缺省地址http://server.com:4567
就可以看到一个创建新Home页面的界面,随便输入两句话,点击保存就可以看到结果了,这很难吗?
话说三年前我也是做到了这一步,然后看了三秒钟,觉得这界面真TMD丑,果断放弃,没想到三年后我胡汉三又回来了,这次怎么也得多走两步啊。
再次出发
首先一个真正的码农是不会满足于直接使用gollum内置的web服务,必须搞成专门的web服务,而且必须是后台服务;怎么可以对外暴露4567这么low的端口的,那必须改;而且直接访问根路径就可以访问到wiki,那怎么行,必须加一个content path,这也必须改;界面上怎么有那么多功能按钮,看起来好丑,不是说好极简风格的吗?改!居然没有用户管理,最in的OAuth授权呢,必须加!
unicorn
unicorn官方给出的宣传语是
Rack HTTP server for fast clients and Unix
不管怎么样,总是一个专业的web服务器,而且也是gem管理的,安装方便啊!先装为敬
gem install unicorn
不过这软件的文档可是真难找,不过我已经为大家准备好了一个配置文件,拿走不谢!
# unicron.conf
worker_processes 2
working_directory '/home/wiki'
#listen '/tmp/unicorn.sock', :backlog => 1024
listen 4567, :tcp_nopush => true
timeout 10
pid '/tmp/gollum.pid'
preload_app true
stderr_path '/home/wiki/logs/unicorn.log'
before_fork do |server, worker|
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
sleep 1
end
after_fork do |server, worker|
addr = "127.0.0.1:#{4568 + worker.nr}"
server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => 1)
end
另外gollum也需要一个配置文件config.ru
,不过那个配置文件一言难尽,先给个简易版本的
#!/usr/bin/env ruby
require 'rubygems'
require 'gollum/app'
gollum_path = File.expand_path('/home/wiki/docroot')
Precious::App.set(:gollum_path, gollum_path)
Precious::App.set(:default_markup, :markdown)
# Specify the wiki options.
wiki_options = {
:base_path => '/wiki',
:universal_toc => false,
:live_preview => false,
:allow_uploads => false,
:h1_title => true,
:allow_editing => true
}
Precious::App.set(:wiki_options, wiki_options)
run Precious::App
此时可以执行以下命令启动unicorn的后台模式
unicorn -D -c /home/wiki/config/unicorn.conf config.ru
启动之后就可以看到gollum启动一样的界面了。
反向代理
常见的有两个软件可以实现端口隐藏,一个是nginx
,另一个就是Apache Httpd
,配置也相对简单,下面我把两种代理配置都贴出来。
Nginx
server {
listen 80;
server_name localhost;
access_log /home/wiki/logs/nginx_access_log;
error_log /home/wiki/logs/nginx_error_log info;
location /wiki {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://localhost:4567;
proxy_redirect off;
}
}
Apache Httpd
ProxyPass /wiki http://localhost:4567
ProxyPassReverse /wiki http://localhost:4567
这两个配置都是把访问/wiki
的请求转移到了内部的4567端口,即隐藏了4567端口,又设置了wiki的content path,一举两得!
呸!想的美,反转来了!怎么访问4567端口都是正常的,访问80端口的/wiki就出现了各种问题,首先是直接跳转到了/Home,出404错误,访问/wiki/Home,则只有文字,所有的css和js都加载不到,仔细一看,见了鬼了,返回到所有路径居然都是直接指向根路径!我不是已经在config.ru文件中设置了base_path为/wiki了吗?
码农专用
这时候就体现出码农的基本素质了,有问题,看源码,反正gollum的源码都在,不是吗?经过简单排查(也就花了几分钟不止),发现我传进去的参数居然被在内部重新赋值了,我晕!不是应该用参数给内部变量赋值的吗?这个开发人员当时是怎么想的?
#/opt/rh/rh-ruby24/root/usr/local/share/gems/gems/gollum-4.1.4/lib/gollum/app.rb:101
# above will detect base_path when it's used with map in a config.ru
settings.wiki_options.merge!({ :base_path => @base_url })
不管了,先改了再说
# above will detect base_path when it's used with map in a config.ru
# settings.wiki_options.merge!({ :base_path => @base_url })
@base_url = settings.wiki_options.fetch(:base_path, @base_url)
改了之后记得要重新启动unicorn,立马效果不一样,80端口的/wiki界面终于正常了。当然在这个文件里还有一些重定向的函数也有问题,一并改了,改得并不彻底,先用着吧。
redirect to("#@base_url/create/#{encodeURIComponent(@name)}")
redirect to("#@base_url/#{page.escaped_url_path}") unless page.nil?
redirect to("#@base_url/")
redirect to("#@base_url/#{clean_url(::File.join(page_dir, page.escaped_url_path))}")
redirect to("#@base_url/#{clean_url(::File.join(encodeURIComponent(page_dir), encodeURIComponent(path), encodeURIComponent(name)))}")
redirect to("#@base_url/create/#{clean_url(encodeURIComponent(page_path))}")
做事就要一气呵成,不是嫌功能按钮太多不美观吗?顺手都改了
#/opt/rh/rh-ruby24/root/usr/local/share/gems/gems/gollum-4.1.4/lib/gollum/templates/page.mustache
把不需要的多余按钮全删除了,只留两个!
目前为止,5个目标已经实现了4个,也算是基本成功了!
最后的冲刺
都说码农是追求完美的,那必须把第5个目标也实现了!为gollum
加上OAuth认证机制。这里先科普一下,gollum
本身是不带用户管理的,需要使用一个叫omnigollum
的插件进行外挂处理,而这个插件也继承了gollum
的风格,本身只做了一个权限管理的平台,本身并不带真正的权限管理,需要使用一个叫omniauth
的插件来实现权限管理,最后这个omniauth
也是一个平台,本身也并不实现权限认证,需要你选择一个真正的认证插件来实现,例如有面向Twitter的认证插件、面向Facebook的认证插件等等,说了一堆,不知道你有没有了解清楚呢,让我们来看看下面这个列表吧
gollum
- omnigollum
- omniauth
- omniauth-twitter
- omniauth-facebook
- omniauth-github
...
好吧,歪果码农做事就是这么,怎么说呢,专业吧!(手动滑稽)
开始安装以上一系列软件,这里我选的是github认证插件,原因很简单,twitter和facebook国内用不了,国内微信、支付宝的认证插件又没有找到,那就只能这样了!
gem install omnigollum omniauth omniauth-github
安装之后,需要做的准备工作就是去github上申请一个clientID和secretKey,这个申请过程我就省略了,可以直接查github的说明,给个图吧
github apps
其中最主要的是Authorization callback URL
http://your.server.com/__omnigollum__/auth/github/callback
是时候把config.rb
的另外一半补上了,下面是个全的
#!/usr/bin/env ruby
require 'rubygems'
require 'gollum/app'
gollum_path = File.expand_path('/home/wiki/docroot')
Precious::App.set(:gollum_path, gollum_path)
Precious::App.set(:default_markup, :markdown)
# Specify the wiki options.
wiki_options = {
:base_path => '/wiki',
:universal_toc => false,
:live_preview => false,
:allow_uploads => false,
:h1_title => true,
:allow_editing => true
}
Precious::App.set(:wiki_options, wiki_options)
# Set as Sinatra environment as production (no stack traces)
Precious::App.set(:environment, :production)
# Setup Omniauth via Omnigollum.
require 'omnigollum'
require 'omniauth/strategies/github'
options = {
# OmniAuth::Builder block is passed as a proc
:providers => Proc.new do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], {
scope: "user",
provider_ignores_state: true
}
end,
:dummy_auth => false,
# Make the entire wiki private
# :protected_routes => ['/*'],
# Specify committer name as just the user name
:author_format => Proc.new { |user| user.name },
# Specify committer e-mail as just the user e-mail
:author_email => Proc.new { |user| user.email },
:authorized_users => nil
}
# :omnigollum options *must* be set before the Omnigollum extension is registered
Precious::App.set(:omnigollum, options)
Precious::App.register Omnigollum::Sinatra
run Precious::App
其中GITHUB_KEY
和GITHUB_SECRET
的值就是刚才申请到的,可以在环境变量中进行设置。
是不是一切都OK了?现在都已经不敢说这句话了!
话说其实已经差不多了,但如果在界面上显示一下已经登录的用户名,另外再增加了一个Login和Logout的按钮是不是会更爽?这些已经有人考虑到了,请按照这篇中提到的地方进行修改吧
https://github.com/arr2036/gollum/commit/dd1fdad59d9f12bfe637704c0101af96aaa1a7e4
真的是写在后面的话
安装gollum对我来说绝对是一个有趣的过程,我之前从来没有接触过ruby,但通过这次安装,又结识了一门新的语言,感觉很不错!安装只是一个起点,不断有新的想法,然后不断去实现它,才是乐趣所在!
Git地址
https://github.com/arr2036/omnigollum
https://github.com/omniauth/omniauth
https://github.com/omniauth/omniauth-github
参考文献
https://cn.charlee.li/gollum-lightweighted-wiki-engine.html
http://railscasts.com/episodes/304-omniauth-identity