Ploneのインストール [Plone4.0]
インストール
poppler-utilsのインストール
poppler-utils を事前にシステムにインストールしておくことで、PDF の本文を検索対象に含めることができる。yum 等でインストールする。
yum install poppler-utils
Unified Installerでのインストール
http://plone.org/ よりダウンロードしインストールする。ここではバージョン 4.0.7 を Standalone で利用する。
# tar zxvf Plone-4.0.7-UnifiedInstaller.tgz # cd Plone-4.0.7-UnifiedInstaller # ./install.sh standalone
デフォルトでは /usr/local/Plone にインストールされ、/usr/local/Plone/zinstance に Plone のインスタンスが作成される。後でインスタンスのみ追加できるよう、上で生成されたファイルは残しておく。インスタンスを追加する場合は、次のようにする。
# ./install.sh --target=/usr/local/Plone4 --instance=zinstance2 standalone
Pythonのデフォルトエンコーディングの設定
Zope は文字コードを UTF-8 で扱うため、Python のデフォルトエンコーディングを UTF-8 とする。/usr/local/Plone/Python-2.4/lib/python2.4/site-packages /sitecustomize.py ファイルを作成し以下のように記述すればよい。
import sys sys.setdefaultencoding("utf-8")
WvWareのインストール
poppler-utils を事前にシステムにインストールしておくことで、WORD の本文を検索対象に含めることができる。必要なパッケージを事前にインストールしておく。
# yum install glib2-devel libgsf-devel
Wv を http://sourceforge.net/projects/wvware/files/ よりダウンロードしてソースからインストールする。
# tar zxvf wv-1.2.4.tar.gz # cd wv-1.2.4 # ./confiture # make # make install
/usr/local/bin にインストールされるため base.cfg を編集して環境変数も設定しておく。
environment-vars = PYTHON_EGG_CACHE ${buildout:directory}/var/.python-eggs + PATH /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
次に設定を反映する。
# bin/buildout
c2.patch.filenamenormalizerのインストール
デフォルトではファイルダウンロード時にファイル名がid表示になってしまう点を修正する。デフォルトでは画像表示時に、ダウンロードダイアログが出てしまうため、ソースからインストールして一部修正を行う。ダウンロードは http://pypi.python.org/pypi/c2.patch.filenamenormalizer より行える。
# tar zxvf c2.patch.filenamenormalizer-1.0a5.tar.gz # mv c2.patch.filenamenormalizer-1.0a5 $PLONE_INSTANCE/src/c2.patch.filenamenormalizer
次に c2.patch.filenamenormalizer/c2/patch/filenamenormalizer/monkey.py の下記のように修正する。
#!/usr/bin/env python
# encoding: utf-8
"""
monkey.py
Created by Manabu Terada on 2010-01-08.
Copyright (c) 2010 CMScom. All rights reserved.
"""
import urllib
from email.Message import Message as emailMessage
from Acquisition import aq_get
from webdav.common import rfc1123_date
from Products.Archetypes.Field import FileField
#from Products.Archetypes.utils import contentDispositionHeader
from config import *
from logging import getLogger
logger = getLogger(__name__)
info = logger.info
try:
from plone.app.blob import field
from plone.app.blob.download import handleIfModifiedSince, handleRequestRange
IS_BLOB = True
except ImportError:
IS_BLOB = False
def get_header_value(ua, filename, instance):
cdisposition = (filename[-4:]=='.swf') and 'inline' or 'attachment'
if ('MSIE' in ua or 'Edge' in ua) and not JA_DEPENDENCE:
filename = urllib.quote(
unicode(filename, instance.getCharset()).encode('utf-8', 'replace'))
else:
filename = unicode(filename, instance.getCharset()).encode(charset, 'replace')
m = emailMessage()
disposition=cdisposition
kw = {'filename' : filename}
m.add_header('content-disposition', disposition, **kw)
header_value = m['content-disposition']
return header_value
def ng_download(self, instance, REQUEST=None, RESPONSE=None, no_output=False):
"""Kicks download.
Writes data including file name and content type to RESPONSE
"""
file = self.get(instance, raw=True)
if not REQUEST:
REQUEST = aq_get(instance, 'REQUEST')
ua = REQUEST.get('HTTP_USER_AGENT')
if not RESPONSE:
RESPONSE = REQUEST.RESPONSE
filename = self.getFilename(instance)
if filename is not None:
header_value = get_header_value(ua, filename, instance)
RESPONSE.setHeader("Content-disposition", header_value)
if no_output:
return file
return file.index_html(REQUEST, RESPONSE)
def blob_index_html(self, instance, REQUEST=None, RESPONSE=None, disposition='inline'):
""" make it directly viewable when entering the objects URL
Original plone.app.blob.field.py
"""
if REQUEST is None:
REQUEST = instance.REQUEST
ua = REQUEST.get('HTTP_USER_AGENT')
if RESPONSE is None:
RESPONSE = REQUEST.RESPONSE
blob = self.getUnwrapped(instance, raw=True) # TODO: why 'raw'?
RESPONSE.setHeader('Last-Modified', rfc1123_date(instance._p_mtime))
RESPONSE.setHeader('Content-Type', self.getContentType(instance))
RESPONSE.setHeader('Accept-Ranges', 'bytes')
if handleIfModifiedSince(instance, REQUEST, RESPONSE):
return ''
length = blob.get_size()
RESPONSE.setHeader('Content-Length', length)
filename = self.getFilename(instance)
if filename is not None:
# filename = IUserPreferredFileNameNormalizer(REQUEST).normalize(
# unicode(filename, instance.getCharset()))
# header_value = contentDispositionHeader(
# disposition=disposition,
# filename=filename)
# RESPONSE.setHeader("Content-disposition", header_value)
header_value = get_header_value(ua, filename, instance)
RESPONSE.setHeader("Content-disposition", header_value)
range = handleRequestRange(instance, length, REQUEST, RESPONSE)
return blob.getIterator(**range)
FileField.download = ng_download
info('patched %s', 'FileField.download')
if IS_BLOB:
field.BlobField.index_html = blob_index_html
info('patched %s', 'field.BlobField.index_html')
最後に設定を反映する。
# bin/buildout
python-ldapのインストール
Python で LDAP を利用するには python-ldap2.3.13 モジュールをインストールする必要がある。まずインスタンス内の buildout.cfg を設定する。
eggs = Plone : + python-ldap==2.3.13
次に設定を反映する。
# bin/buildout
インストールには openldap-devel と openssl-devel を組み込んでおく必要がある。インストールされていない場合は先に yum 等でインストールすればよい。
# yum install openldap-devel openssl-devel
起動確認
Plone が起動することを確認する。
# cd /usr/local/Plone/instance # bin/plonectl start
http://ホスト名:8080/ にアクセスして Plone のページが表示されればインストール成功である。Plone の停止は次のコマンドを実行する。
# bin/plonectl stop
全体の管理者の設定
インストールすると admin ユーザが生成される。パスワード等は /usr/local/Plone/instance/adminPassword.txt に書かれている。ZMI(http://ホスト名:8080/manage)にアクセスしこのユーザでログインし、/acl_users/users で新しいユーザを追加する。
User ID: admtest Login name: admtest Password: **** Confirm password: ****
次に /acl_users/roles で追加したユーザに Manager ロールを与える。最後にデフォルトで作成されていた admin ユーザもパスワードを変更しておく。パスワードが分からなくなった場合は、次のコマンドで臨時ユーザを追加できる。
# bin/instance adduser <username> <password>
Ploneサイトの追加
ZMI(http://ホスト名:8080/manage)にアクセスし全体の管理者でログインする。複数のPloneを追加する場合は、右上のドロップダウンリストより Plone Site を追加する。
Id : web1 Title : WEB1 アドオン : WorkflowPolicySupport
設定ファイルの編集
設定ファイルを変更後は、設定反映後再起動すれば利用できる。
# bin/buildout # bin/plonectl stop; bin/plonectl start
HTTP起動ポートの設定
Zope インスタンス内の buildout.cfg で設定する。
http-address = 9081
その他
$PLONE_INSTANCE : /usr/local/Plone/zinstance (Plone のインスタンス)
自動起動
起動スクリプトを /etc/init.d/plone として次のように作成し、パーミッションを適宜設定する。
#!/bin/sh # Startup script for Plone # # chkconfig: - 80 20 # description: Zope, a web application server # # config: $instance/buildout.cfg # config: $instance/parts/instance/etc/zope.conf # Source function library. . /etc/init.d/functions RETVAL=0 plonectl="/usr/local/Plone/zinstance/bin/plonectl" prog="plone" start() { output=`$plonectl start` # the return status of plonectl is not reliable, we need to parse # its output via substring match if echo $output | grep -q "started"; then # success action $"Starting $prog: " /bin/true touch /var/lock/subsys/$prog RETVAL=0 else # failed action $"Starting $prog: " /bin/false RETVAL=1 fi return $RETVAL } stop() { output=`$plonectl stop` # the return status of plonectl is not reliable, we need to parse # its output via substring match if echo $output | grep -q "stopped"; then # success action $"Stopping $prog: " /bin/true rm -f /var/lock/subsys/$prog RETVAL=0 else # failed action $"Stopping $prog: " /bin/false RETVAL=1 fi return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; status) $plonectl status ;; restart) restart ;; condrestart) [ -e /var/lock/subsys/$prog ] && restart ;; *) echo $"Usage: $0 {start|stop|status|restart|condrestart}" RETVAL=1 esac exit $REVAL
作成後は
/sbin/chkconfig --add plone
でzopeを起動スクリプトとして追加し、
/usr/sbin/ntsysv
で起動時に自動起動されるようにする。以降の起動・停止等は
/sbin/service plone [start | stop | restart | status | condrestart]
で行える。
ログのローテーション
Zope のログは $PLONE_INSTANCE/var/log/ 内に、instance-Z2.log(アクセスログ)、instance.log(エラー情報等)が出力されるがローテーションはされない。そこで logrotate を用いてログのローテーションを行う。/etc/logrotate.d/plone に以下を記述すればよい。
$PLONE_INSTANCE/var/log/instance-Z2.log $PLONE_INSTANCE/var/log/instance.log { weekly <- 毎週ログローテーション rotate 20 <- ローテーション回数 create 600 plone plone <- パーミッション、ユーザ名、グループ名 missingok <- ログファイルが存在しなくてもエラーを出さない notifempty <- ログファイルが空ならローテーションしない compress <- ローテーションされたログをgzipで圧縮 sharedscripts <- 複数指定したログファイルに対してpostrotateを実行 postrotate <- ログローテーション後に実行するコマンド /bin/kill -USR2 $(cat $PLONE_INSTANCE/var/instance.pid) endscript }
ZODB の自動 Pack
ZODB の Pack は Control_Panel/Database/main より行うことができるが、手動で行う必要があるため、これを cron で自動実行するように設定する。これは、wget 等で管理者パスワードを BASIC 認証に渡すこともできるが、管理者パスワードを記述するのにはセキュリティ上好ましくない。そのため、以下のように設定する。
スクリプトの作成
Zope のルートの zope_management_scripts フォルダ内(独自に作成)に、zope_pack という名前のスクリプトを作成する。days パラメータにより、何日前までの undo データを残すかを設定すればよい。
try: context.aq_parent.Control_Panel.Database.manage_pack(days=7) return 'OK' except: return 'NG'
ZODB の Pack には Manager 権限が必要なので、Proxy タブより Proxy Roles として Manager を選択する。
Proxy Roles : Manager
これにより、このスクリプトにアクセスするユーザが Manager でなくても、スクリプトに書かれた Pack を実行できる。
セキュリティの設定
この状態では、ログインしなくても実行できるため、スクリプトの Security タブよりセキュリティ設定を次のように設定し、Manager 権限でのみ実行できるようにする。
Manager : Change Python Scripts のみOFF, 他全てON その他Acquire?を含め : 全てOFF
Change Python Scripts を OFF にすることで、Manager でもこのスクリプトの変更を禁止する。変更が必要な場合は、改めてこのパーミッションを ON とすればよい。これは、Proxy Roles の設定で Manager を設定しているため、スクリプトの改ざんにより悪用されることを防ぐためである。
ユーザの作成
Zope のルートの acl_users/users で Anonymous として update 用のユーザを設定する。Anonymous とするには、このユーザに acl_users/roles でどのロールも与えなければよい。このユーザを用いることで、たとえこのパスワードが漏れたとしても Zope の設定変更等は行えない。
ユーザ名 : zope_conf_user
ローカルロールの設定
さらに、スクリプトの Security タブより、上記ユーザに local role として、Manager 権限を与える。
User : zope_conf_user Roles : Manager
このようにすることで、このユーザは、Pack の実行を除き何もできない。
自動実行
最後に root の cron で wget 等を動かし、スクリプトにアクセスして Pack を実行させればよい。
15 2 * * 0 wget --no-proxy --http-user="zope_conf_user" --http-passwd="XXX" --delete-after http://localhost:9380/zope_management_scripts/zope_pack
PloneとApacheの連携
Apache のバーチャルホスト経由で Plone にアクセスする仕組みを構築する。
Web サイトのホスト : www.example.ac.jp Plone のホスト : 192.168.2.2
モジュールの追加
mod_rewrite と mod_proxy が必要なので、読み込む設定を追加する。
/etc/httpd/conf/httpd.conf (抜粋)
LoadModule rewrite_module modules/mod_rewrite.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so
rewriteの設定
http でのアクセスを Apache でプロクシする場合は /etc/httpd/conf/httpd.conf の適当な場所(VirtualHost ディレクティブ内等)に、Zope の VirtualHostMonster が理解できる形で記述する。
RewriteEngine On RewriteRule ^/XXX[/]?(.*) http://192.168.2.2:8080/VirtualHostBase/http/www.example.ac.jp:80/YYY/VirtualHostRoot/_vh_XXX/$1 [P]
この例は Plone サイトに直接アクセス(http://192.168.2.2:8080/YYY)するかわりに、Apache 経由(http://www.example.ac.jp/XXX)でアクセスできるように書き換えを行った例である。
同様に、https でのアクセスを Apache でプロクシする場合は /etc/httpd/conf.d/ssl.conf の適当な場所(VirtualHost ディレクティブ内等)に、設定を記述する。
RewriteEngine On RewriteRule ^/XXX[/]?(.*) http://192.168.2.2:8080/VirtualHostBase/https/www.example.ac.jp:443/YYY/VirtualHostRoot/_vh_XXX/$1 [P]
この例では、Plone サイトに直接アクセス(http://192.168.2.2:8080/YYY)するかわりに、Apache 経由(https://www.example.ac.jp/XXX)でアクセスできるように書き換えが行われる。ただし、Web サイトと Plone サイト間の通信は暗号されない。
さらにログイン時のみSSL接続とするには、最終的に次のように設定すれば良い。
- http.conf
<VirtualHost www.example.ac.jp:80>
ServerName www.example.ac.jp:80
(中略)
RewriteEngine On
# 各種ログインURL
RewriteRule ^/(.*login_form$|.*require_login$) https://%{HTTP_HOST}/$1 [R]
# Ploneの表示
RewriteRule ^/(.*) http://192.168.2.2:8080/VirtualHostBase/http/%{HTTP_HOST}:80/YYY/VirtualHostRoot/_vh_/$1 [P]
</VirtualHost>
- ssl.conf
<VirtualHost www.example.ac.jp:443>
ServerName www.example.ac.jp:443
(中略)
RewriteEngine On
# ログアウト
RewriteCond %{HTTP_REFERER} https://(www.example.ac.jp.*)
RewriteRule ^/.*logged_out http://%1 [R]
# Ploneの表示
RewriteRule ^/(.*) http://192.168.2.2:8080/VirtualHostBase/https/%{HTTP_HOST}:443/YYY/VirtualHostRoot/_vh_/$1 [P]
</VirtualHost>