Flat ODFとRedmine, Git(Gitolite, SparkleShare)で文書共有システムを作ってみた(構築編)

nogajun
nogajun

_

この記事は「LibreOffice Advent Calendar 2013」17日目の記事で、第5回関西LibreOffice勉強会の発表資料です。

複数人で原稿を書くプロジェクトで、原稿の管理もしつつそれに合わせてプロジェクト進行を管理する必要が出てきたのですが、OSC福岡で聞いたCmisSyncがSparkleShareからのフォークという話しと、LibreOfficeのフラットODFを使うとODF文書の差分を取ることができるという話しをヒントに、Redmine, Gitolite, SparkleShare, LibreOfficeを組み合わせてプロジェクト管理とドキュメント管理システムを作ってみたら、意外とうまくいったのでまとめてみました。

どういうことするの?

構成図

一言でいうと文書の共有と管理です。

複数人で原稿を書くプロジェクトとなると原稿の取りまとめをどうするかの問題があります。これを自動化して手間をかけることなく集約と共有する事。それと集約された原稿に対して期限を切ったり指摘をしたりすることがありますが、その管理を集めた先で一元管理。

この2点を実現しています。

フラットOFD(FODF)形式とは

フラットODFというファイル形式は、OSC福岡でLibreOffice日本語チームの大森さんに教えてもらうまで知らなかったのですが、このシステムを作るきっかけになったので紹介します。

フラットODF形式は、一つのXMLファイル(Open Document XML)の中に文書と文書情報、Base64でエンコードされたイメージファイルなどが埋め込まれたオフィス文書形式のファイルです。

ODF 1.2から規格に入っていたそうです。

- Flat ODF as the Swiss Army Knife (PDF): http://plugfest.opendocsociety.org/lib/exe/fetch.php?media=plugfests:201210_berlin:fridrichplugfestberlin2012.pdf

通常のODF形式のファイルは、文書や画像など複数のファイルをまとめてzipで圧縮したファイルなので、文書ファイルの差分が取りにくいなどがありましたが、FODF形式のファイルは単一のテキストファイルなので差分を取ることが簡単にできます。

FODF形式の欠点

FODF形式の欠点としては、非圧縮かつ画像をBase64エンコーディングで埋め込むのでファイルが大きくなる事が挙げられます。しかし、大容量HDDが搭載されているマシンがほとんどの現在では気になることはないと思います。

ODF形式への変換

ODF形式に戻したい場合は、LibreOfficeでFODF形式のファイルを開き、ODF形式で保存しなおせば元に戻ります。

大量にある場合はコマンドラインからも変換もできます。

soffice --headless --convert-to odt *.fodt

オプションの意味です。

--headless     like invisible but no userinteraction at all.
--convert-to output_file_extension[:output_filter_name] [--outdir output_dir] files
      Batch convert files.
      If --outdir is not specified then current working dir is used as output_dir.
      Eg. --convert-to pdf *.doc
          --convert-to pdf:writer_pdf_Export --outdir /home/user *.doc

使用するソフトウェア

さてシステムの話に入ります。文書共有システムで使用したソフトウェアはこんな感じです。

  • サーバー側(Debian Wheezy)

    • Redmine: プロジェクト管理システム
    • Gitolite: gitリポジトリ管理システム
      • Git: 分散バージョン管理システム
  • クライアント側 (Debian Sid / Windows 7)

    • SparkleShare: gitを利用したファイル同期・共有ソフトウェア
      • Git: 分散バージョン管理システム
    • LibreOffice: 言わずとしれたオープンソースなオフィスソフトウェア

環境はサーバー側はDebian 7.x(Wheezy)、クライアント側はDebian SidとWindows 7です。クライアントはMacでも大丈夫なはずです。

セットアップの流れ

セットアップの流れとしては、プロジェクトとファイルを管理するサーバー(RedmineとGitolite3)と文書を作成するクライアント(SparkleShareとLibreOffice)の二つに別れます。

それではサーバー側から説明します。


Redmineのセットアップ

まずプロジェクト管理のRedmineをインストールします。

Redmineはプロジェクト管理と同時にGitリポジトリのビュワーとしても利用できるので、これを利用するとオフィス文書の履歴や差分を見ることができます。

インストールですがDebianですのでaptだけで終了します。

# apt-get install redmine redmine-sqlite apache2 libapache2-mod-passenger

バックエンドや設定を変更したい場合は以前の日記を参考にしてください。

http://localhost/redmine/ のようにローカルで起動するだけであれば設定は、こんな感じでよいと思います。

# cp /usr/share/doc/redmine/examples/apache2-passenger-alias.conf /etc/apache2/sites-available/redmine
# a2ensite redmine
# service apache2 reload

テストではVagrant上で構築して、http://192.168.33.10/redmine/で確認していました。 (Vagrantfileの設定「config.vm.network :private_network, ip: "192.168.33.10"」)

このような場合は、Apacheのdefault設定を無効にしてVirtualHostをワイルドカードにするとよいでしょう。

   # a2dissite default
   # sed -i 's/localhost>/\*:80>/' /etc/apache2/sites-available/redmine
   # service apache2 reload

Redmineをインストールしたサーバーにブラウザでアクセスしてログインできることが確認できれば、ユーザーと確認用プロジェクトを作成しておきます。

ファイル共有と直接関係はありませんが、文字コードがUTF-8以外のファイルは、リポジトリブラウザで文字化けするので、redmineの「管理」→「設定」にある「添付ファイルとリポジトリのエンコーディング」に「utf-8,cp932,euc-jp」 と文字コードの設定を追加しておきます。


Gitolite3のセットアップ

Gitoliteは、分散バージョン管理システム「git」のリポジトリ管理やユーザーのアクセス制限をおこなうためのソフトウェアです。

SparkleShareを使ってファイルを同期・共有するだけであれば、gitのベアリポジトリを作成すればいいのですが、複数のgitリポジトリを管理したり、ユーザーごとのアクセス制限をおこなう場合は途端に管理が複雑になってくるので、Gitoliteを利用してリポジトリ管理とアクセス制限をします。

WheezyではGitolite(2)のほかに、Wheezy BackportsにGitolite3が用意されているので今回はこちらを使いました。

- http://packages.debian.org/wheezy-backports/gitolite3

Wheezy Backportsを利用するには、apt-lineを追加する必要があるので追加しておきます。

$ vi /etc/apt/sources.list.d/wheezy-backports.list

## Debian Backports
deb http://ftp.jp.debian.org/debian wheezy-backports main contrib non-free
deb-src http://ftp.jp.debian.org/debian wheezy-backports main contrib non-free

Gitolite3のインストールもaptだけで終わりますが、インストールの際に Gitolite管理者用の SSH鍵が必要になるので先に作成しておきます。

   $ ssh-keygen
   Generating public/private rsa key pair.
   Enter file in which to save the key (/home/user/.ssh/id_rsa): gitolite-admin
   Enter passphrase (empty for no passphrase):
   Enter same passphrase again:

もし、SSH鍵を作らずインストールしても、あとで「dpkg-reconfigure gitolite3」と再設定すれば登録できるので安心してください。

鍵ペアができたら公開鍵(例ではgitolite-admin.pub)をサーバーにコピーしておきます。秘密鍵は~/.ssh/に保存し、~/.ssh/configにGitolite管理者リポジトリアクセス用の設定を書いておきます。

   Host example.com
     Hostname example.com
     User gitolite3 ← サーバーに作られるGitolite3専用ユーザー
     IdentityFile ~/.ssh/gitolite-admin
     IdentitiesOnly yes

準備ができたところでGitolite3をインストールします。 ここで一つ注意点ですが、backportsリポジトリは明示的に指定しないとインストールできないので、オプションで指定してインストールします。

   # apt-get -t wheezy-backports install gitolite3

debconfの「Administrator's SSH key:」の質問には、あらかじめ作っておいたGitolite管理者用公開鍵(例ではgitolite-admin.pub)の場所を指定します。

Gitoliteの設定

Gitoliteの設定は、管理用リポジトリをクローンして変更します。

   $ git clone ssh://gitolite-test/gitolite-admin
   Cloning into 'gitolite-admin'...

gitolite-adminディレクトリにはconfとkeydirの二つのディレクトリがあり、confディレクトリのgitolite.confファイルには設定があります。keydirディレクトリには、gitリポジトリを利用するユーザーの公開鍵を置きます。

共有リポジトリの設定はあとで行うので、管理用リポジトリがクローンできたことが確認できれば次に進みます。


RedmineからGitolite3リポジトリを参照する

Redmineはgitリポジトリが参照できるので、設定をすればgitリポジトリのどのファイルが更新されたか確認できます。

しかし、Gitolite3は専用ユーザー・グループ「gitolite3」が管理しており、gitolite3ユーザー以外参照ができないようになっているので、そのまま設定しても参照はできません。

ということで、Redmine(を動かしているApache)のユーザー「www-data」をGitolite3グループに所属させ、Gitolite3が作成するリポジトリのパーミッションをグループまで参照できるよう設定を変更して、RedmineからGitリポジトリを参照できるようにします。

Gitolite3グループにApacheのユーザー(www-data)を追加します。

   # gpasswd -a www-data gitolite3
   ユーザ www-data をグループ gitolite3 に追加

gitolite3グループにwww-dataユーザーが追加されました。

   # id www-data
   uid=33(www-data) gid=33(www-data) groups=33(www-data),105(gitolite3)

/var/lib/gitolite3/.gitolite.rc のUMASK設定を0077から0027に変更してグループに所属していればリポジトリを見られるようにします。

   # default umask gives you perms of '0700'; see the rc file docs for
   # how/why you might change this
   UMASK                           =>  0027,

これでRedmineからGitolite3が作成するリポジトリを参照できるようになりました。

gitリポジトリの作成

サーバー側の設定が終わったのでクライアント側の設定ですが、その前にファイルを共有・管理するためのgitリポジトリを作成します。

gitリポジトリの作成は、gitolite-adminリポジトリにある設定ファイルgitolite.confにリポジトリ設定を追加すると自動的に作成されます。

gitolite-admin/confi/gitolite.confファイルををエディタで開くと、このように書いてあります。

   repo gitolite-admin
       RW+     =   admin

   repo testing
       RW+     =   @all

repoの後に続く名前がリポジトリ名で、gitolite-adminリポジトリはgitolite管理用のリポジトリです。testingリポジトリはgitoliteテスト用にあらかじめ用意されているリポジトリです。不要なら削除してもかまいません。

gitoliteの詳しい設定については、gitoliteのサイトを参照してもらうとして、リポジトリ以外を簡単に説明すると「RW+」と書いてある部分はアクセス権です。読み・書き・巻き戻し全て可能な状態になっています。

イコールを挟んで「@all」の部分はアクセスできるユーザー・グループの指定です。「@」がつくとグループ、無いとユーザーの指定になります。

ユーザー名は、keysディレクトリに置くSSH公開鍵ファイル「(ユーザー名).pub」のユーザー名部分になります。

ひとまずテスト用にsparkletestという名前で、すべてのユーザーが読み書き巻き戻し可のリポジトリを作成しました。

   repo sparkletest
       RW+     =   @all

設定を変更したなら、git add/commitしてpushすれば設定が更新されます。

リポジトリを削除する場合は、gitolite.confの該当リポジトリの設定を削除後、git add/commi/pushして設定を更新。その後、サーバー側にあるリポジトリを削除すればリポジトリの削除は完了します。

Redmineのリポジトリブラウザに登録する

リポジトリが作成できたら、Redmineのリポジトリブラウザにgitリポジトリを登録します。登録方法は、Redmineにログインしてプロジェクトの「設定」→「リポジトリ」タブを開きます。

適当な識別子を設定し、パスは、Gitoliteが管理するGitリポジトリが「/var/lib/gitolite3/repositories/(リポジトリ名).git」にあるので、この場所を入力して「保存」すれば登録は完了です。


クライアントの設定

ここからはクライアント側の設定に入ります。

クライアント側は基本的に難しいことしませんが、文書を共有管理するために二つだけお願いをします。

  1. SparkleShareをインストールして設定すること。
  2. LibreOffice Writerの文書ファイルはFODT形式で保存すること。

SparkleShareのインストールと管理

SparkleShareのインストールは、Debianならapt-get install sparkleshare、Windowsならmsiファイルをダブルクリックしてインストールするだけです。

SparkleShareに共有リポジトリを登録する方法ですが、SparkleShareのWikiを見ると自動送信できるようですが、今回はそこまで準備する時間がなかったので手動で登録することにしました。

手動でサーバーに登録する流れとしては、

  1. SparkleShareインストールして管理者に「Client ID」(SparkleShareが生成するSSH公開鍵)を送ってもらう。
  2. 管理者は送ってもらった鍵をGitoliteに登録して、共有リポジトリの設定をユーザーに伝える。
  3. ユーザーが共有リポジトリを設定するとファイル共有開始。

ということで、管理者がSparkleShareのSSH公開鍵(Client ID)を受け取った後のGitoliteの設定について説明します。

  1. 送ってもらったSSH公開鍵をgitolite-admin/keysディレクトリに「(ユーザー名).pub」というファイル名で置きます。
  2. gitolite-admin/conf/gitolite.confのアクセス権を設定します。(必要があるなら。今回の例では不要。)
  3. git add/commitとpushして設定を更新します。

あとはユーザーに設定を伝えるだけです。設定は以下の点を伝えます。

  1. SparkleShareメニューの「Add Hosted Project...」を選ぶ。
  2. On my own server」を選択して以下の部分を入力する。
    • Address: ssh://gitolite3@(サーバー名)
    • Remote Path: /(リポジトリ名)

設定を説明すると「Address」のプロトコル「ssh://」に続く「gitolite3」は、Gitolite3のユーザー名です。「Remote Path」は、そのままリポジトリ名です。

登録できれば、SparkleShareディレクトリ以下にあるリポジトリディレクトリ(~/SparkleShare/(リポジトリ名)/)に適当なファイルを置いてみてください。Dropboxのように自動的にサーバーにpushされるので、Redmineのリポジトリブ ラウザで登録されたか確認します。


LibreOfficeでフラットODFを使う

やっと来ました!文書の作成と管理です!

この文書作成と管理がなければ、ただの「Dropboxもどきを作ろう」で終わってしまいますが、このシステムが本領を発揮するのはここからです。

まずLibreOffice Writerを起動して適当な文書を書き、SparkleShareのリポジトリディレクトリにFODT形式で保存してください。

Redmineのリポジトリブラウザを見るとFODT形式で保存したファイルが登録されているので、上書き保存をしながら何回か文書を変更してみてください。

そうするとRedmineリポジトリに「差分を見る」というボタンがあるので押してみましょう。

差分情報が表示されますが、いくつか変更された文書情報に続いて変更された本文が表示されるはずです。


まとめ

ということで、ユーザーはgitを意識することなくサーバーに原稿をpushすることができるし、管理者は原稿の差分(更新具合)を見ながらチケットを切ったりできるようになりましたとさ。


既知の不具合

WindowsのSparkleShareから日本語ファイル名を使ったファイルをコミットすると、コミットログが文字化けする。(ファイル名は問題なし)

デバッグログを見るとコミット時点のメッセージが文字化けしてるから、ファイル名の受け渡しに問題あるような気がするけど、Windowsに愛がないので調べる気が無いです。


明日のLibreOffice Advent Calendarは大橋さんです。 明日も楽しみですね!

_ Ansibleでdebconfの設定はどうしたらいいんだろう

上の記事でどうせならAnsibleで自動化したらいいかなと思ってPlaybookを書き始めたけど、Gitolite3のインストールでdebconfの公開鍵登録がうまくいかない。

  - name: set debconf
    command: "{{item}}"
    with_items:
      - echo "gitolite3 gitolite3/gituser string gitolite3" | debconf-set-selections
      - echo "gitolite3 gitolite3/gitdir string /var/lib/gitolite3" | debconf-set-selections
      - echo "gitolite3 gitolite3/adminkey string /home/vagrant/gitolite3_admin.pub" | debconf-set-selections

こんな感じに書いた後にインストールしているのだけど何か間違ってるのだろうか。