Wiki do Laboratório MARTIN → Instalação do Wiki do MARTIN
 
 

Instalação do Wiki do MARTIN

Last modified on Monday, November 16th 2009 at 7:57 PM.

A arquitetura do Wiki do MARTIN possui dois componentes: o Nanoki, responsável pela gerência de conteúdo, e o Apache2, responsável pela autenticação de páginas de edição do Nanoki. Na arquitetura do Wiki do MARTIN o Apache2 atua como um proxy reverso para o Nanoki.

OBS1: em todas as referências abaixo a "?.?.?", substituir pelos números da versão correta de cada pacote.

OBS2: assume-se a instalação em uma máquina Ubuntu associada ao domínio DNS wiki.martin.lncc.br .

Instalação do Nanoki

OBS: Na instalação do Nanoki, optou-se por instalar todas as dependências desse sistema no home de um novo usuário (wikimartin) sem permissão de sudo, facilitando a migração desse componente para outra máquina e diminuindo eventuais riscos de segurança.

Logar na máquina-alvo como operador ou qualquer outro usuário com permissão de sudo.

Criar um usuário wikimartin e logar como esse usuário:

sudo adduser wikimartin
su - wikimartin

Baixar, compilar e instalar Lua:

cd ~
wget http://www.lua.org/ftp/lua-?.?.?.tar.gz
tar zxvf lua-?.?.?.tar.gz
cd lua-?.?.?
vim src/luaconf.h

Editar linha:

#define LUA_ROOT "/home/wikimartin/lua-5.?.?/"

make linux local

OBS: pode ser necessária a instalação das bibliotecas de readline, history e ncurses para Lua compilar corretamente. Com o comando apt-cache search readline pode-se descobrir o nome do pacote na versão Ubuntu específica sendo utilizada (ex. libreadline5 e libreadline5-dev).

Testar Lua:

~/lua-?.?.?/bin/lua
> print"hello" 

Baixar, compilar e instalar LuaFileSystem:

cd ~

Descobrir em http://luaforge.net/projects/luafilesystem/ link para última versão e baixar com wget

tar zxvf luafilesystem-?.?.?.tar.gz
cd luafilesystem-?.?.?
vim config

Editar linhas:

PREFIX=/home/wikimartin/lua-?.?.?

LUA_LIBDIR= $(PREFIX)/lib/lua/5.1

LUA_INC= $(PREFIX)/include

make
make install

Testar LuaFileSystem:

~/lua-?.?.?/bin/lua -llfs
> print(lfs) -- resultado tem que ser uma table

Baixar, compilar e instalar LuaSocket:

cd ~

Descobrir em http://luaforge.net/projects/luasocket link para última versão e baixar com wget

tar zxvf luasocket-?.?.?.tar.gz
cd luasocket-?.?.?
vim config

Editar linhas:

LUAINC=-I/home/wikimartin/lua-?.?.?/include

INSTALL_TOP_SHARE=/home/wikimartin/lua-?.?.?/share/lua/5.1

INSTALL_TOP_LIB=/home/wikimartin/lua-?.?.?/lib/lua/5.1

make
make install

Testar LuaSocket:

~/lua-?.?.?/bin/lua -lsocket
> print(socket) -- resultado tem que ser uma table

Baixar, compilar e instalar lzlib:

cd ~

Descobrir em `http://luaforge.net/projects/lzlib/' link para última versão e baixar com wget

tar zxvf lzlib-?.?.?.tar.gz
cd lzlib-?.?.?
vim Makefile

Editar linhas:

LUA=/home/wikimartin/lua-?.?.?

LUALIB= $(LUA)/lib/lua/5.1

make
cp zlib.so ~/lua-?.?.?/lib/lua/5.1

Testar lzlib:

~/lua-?.?.?/bin/lua
> zlib = require"zlib" 
> print(zlib) -- resultado tem que ser uma table

OBS1: parece que o módulo lzlib não foi implementado de forma a retornar uma tabela com nome default "zlib", por isso lua -lzlib não funciona (tampouco require"zlib" já no interpretador Lua).

OBS2: pode ser necessária a instalação da biblioteca zlib para o lzlib compilar corretamente. Com o comando apt-cache search zlib pode-se descobrir o nome do pacote na versão Ubuntu específica sendo utilizada (ex. zlib1g-dev).

Baixar, compilar e instalar slncrypto:

cd ~

Descobrir em `http://luaforge.net/projects/sln/' link para última versão do slncrypto e baixar com wget

OBS: não baixar a biblioteca sln (selene) completa! Somente o módulo slncrypto "standalone", pois ele não apresenta dependências de compilação, ao contrário do módulo slncrypto embutido no sln.

bunzip2 slncrypto-?.?.?.tar.bz2
tar xvf slncrypto-?.?.?.tar
cd slncrypto-?.?.?
gcc -c -I ~/lua-?.?.?/include -pedantic -Wall -O2 -fpic -c -o slncrypt.o slncrypt.c  
gcc -O -shared -o ~/lua-?.?.?/lib/lua/5.1/crypto.so slncrypt.o

Testar slncrypto:

~/lua-?.?.?/bin/lua -lcrypto
> print(crypto) -- resultado tem que ser uma table

Baixar e instalar Nanoki:

cd ~
wget http://alt.textdrive.com/assets/public/Nanoki/Nanoki-?.?.?.tar.bz2
bunzip2 Nanoki-?.?.?.tar.bz2
tar Nanoki-?.?.?.tar

Executar Nanoki:

cd ~/Nanoki-?.?.?
../lua-?.?.?/bin/lua Nanoki.lua . 127.0.0.1 9554 forwarded not >/dev/null 2>/dev/null &

OBS: substituir 9554 por outra porta TCP, se for o caso

TODO: os dados do Wiki ficam em ~/Nanoki-?.?.?/wiki. Implementar procedimento de backup automático!

Configurar layout do Nanoki:

cd ~/Nanoki-?.?.?
vim WikiLayout.txt

Incluir as seguintes linhas após <div class='container'>:

        <div class='span-24'>
            <img src='/etc/martin-header-en-long.png'/>
        </div>

OBS: incluir o arquivomartin-header-en-long.png no diretório ~/Nanoki-?.?.?/etc!

Instalação do Apache2 e configuração com Nanoki

Logar na máquina-alvo como operador.

Instalar Apache2:

sudo apt-get install apache2

Habilitar módulos de proxy:

sudo /etc/apache2/mods-available/proxy.load /etc/apache2/mods-enabled/proxy.load
sudo /etc/apache2/mods-available/proxy_http.load /etc/apache2/mods-enabled/proxy_http.load
sudo /etc/apache2/mods-available/proxy.conf /etc/apache2/mods-enabled/proxy.conf
sudo /etc/apache2/mods-available/headers.load /etc/apache2/mods-enabled/headers.load

OBS: pode-se usar também a ferramenta a2enmod para habilitar módulos no apache.

Habilitar módulos de segurança e de reescrita de URLs em cabeçalhos HTTP:

sudo a2enmod ssl
sudo a2enmod rewrite

Instalar módulo de reescrita de URLs em páginas HTML:

sudo apt-get install libapache2-mod-proxy-html

OBS: o módulo já é habilitado na instalação

Configurar proxy:

sudo vim /etc/apache2/mods-enabled/proxy.conf

Substituir "Deny from all" por "Allow from all"

Configurar o virtual host wiki.martin.lncc.br:80 (sem autenticação):

sudo vim /etc/apache2/sites-available/wikimartin

Incluir as seguintes linhas:

NameVirtualHost wiki.martin.lncc.br:80
<VirtualHost wiki.martin.lncc.br:80>
    ServerName wiki.martin.lncc.br
    ServerAdmin NOME-USUARIO-ADMIN@NOME-DOMINIO

    ErrorLog /var/log/apache2/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /var/log/apache2/access.log combined

    <Location />
            ProxyPass http://127.0.0.1:9554/
            ProxyPassReverse http://127.0.0.1:9554/
            SetOutputFilter proxy-html
            ProxyHTMLURLMap http://127.0.0.1:9554/ /
            RequestHeader unset Accept-Encoding
    </Location>

    RewriteEngine on
    #RewriteRule ^/.+/editor.* - [F,L]
    RewriteRule ^/(.+/editor.*) https://wiki.martin.lncc.br/$1 [R]
</VirtualHost>

OBS1: a diretiva RewriteRule é usada para permitir que quaisquer páginas que tem "/editor" na URL (forma do Nanoki identificar páginas de edição de conteúdo) sejam encaminhadas via porta 443/SSL, que demanda autenticação.

OBS2: no caso de páginas que tem "/file" na URL (forma do Nanoki identificar repositórios de arquivos carregados pelo usuário), pode-se desabilitar a reescrita de URLs. Isso é particularmente útil para documentos textuais carregados pelo usuário (por exemplo, arquivos XML). Como exemplo, para a página "NOME-PAG" pode-se incluir, logo abaixo da seção <Location />:

    <Location /NOME-PAG/file/>
            ProxyPass http://127.0.0.1:9554/
            ProxyPassReverse http://127.0.0.1:9554/
    </Location>

Habilitar o o virtual host wikimartin:

sudo a2ensite wikimartin

Criar e povoar arquivo com credenciais de usuários (login/senha):

sudo touch /etc/apache2/httpd.auth-basic
sudo htpasswd /etc/apache2/httpd.auth-basic NOME-USUARIO

OBS: pode-se incluir novos usuários remotamente usando o comando ssh root@MAQUINA-ALVO htpasswd /etc/apache2/httpd.auth-basic NOME-USUARIO

Criar certificado de máquina para o domínio DNS wiki.martin.lncc.br:

sudo make-ssl-cert /usr/share/ssl-cert/ssleay.cnf /etc/ssl/certs/ssl-cert-wiki-martin-lncc-br.crt

OBS: o arquivo ssl-cert-wiki-martin-lncc-br.crt possui tanto o certificado de máquina quanto a chave privada associada.

Configurar o virtual host wikimartin-ssl (com autenticação):

sudo vim /etc/apache2/sites-available/wikimartin-ssl

Incluir as seguintes linhas:

<IfModule mod_ssl.c>
<VirtualHost wiki.martin.lncc.br:443>
    ServerAdmin NOME-USUARIO-ADMIN@NOME-DOMINIO

    ErrorLog /var/log/apache2/error.log

    # Possible values include: debug, info, notice, warn, error, crit,
    # alert, emerg.
    LogLevel warn

    CustomLog /var/log/apache2/ssl_access.log combined

    #   SSL Engine Switch:
    #   Enable/Disable SSL for this virtual host.
    SSLEngine on

    #   A self-signed (snakeoil) certificate can be created by installing
    #   the ssl-cert package. See
    #   /usr/share/doc/apache2.2-common/README.Debian.gz for more info.
    #   If both key and certificate are stored in the same file, only the
    #   SSLCertificateFile directive is needed.
    #SSLCertificateFile    /etc/ssl/certs/ssl-cert-snakeoil.pem
    #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
    SSLCertificateFile    /etc/ssl/certs/ssl-cert-wiki-martin-lncc-br.crt

    #   SSL Engine Options:
    #   Set various options for the SSL engine.
    #   o FakeBasicAuth:
    #     Translate the client X.509 into a Basic Authorisation.  This means that
    #     the standard Auth/DBMAuth methods can be used for access control.  The
    #     user name is the `one line' version of the client's X.509 certificate.
    #     Note that no password is obtained from the user. Every entry in the user
    #     file needs this password: `xxj31ZMTZzkVA'.
    #   o ExportCertData:
    #     This exports two additional environment variables: SSL_CLIENT_CERT and
    #     SSL_SERVER_CERT. These contain the PEM-encoded certificates of the
    #     server (always existing) and the client (only existing when client
    #     authentication is used). This can be used to import the certificates
    #     into CGI scripts.
    #   o StdEnvVars:
    #     This exports the standard SSL/TLS related `SSL_*' environment variables.
    #     Per default this exportation is switched off for performance reasons,
    #     because the extraction step is an expensive operation and is usually
    #     useless for serving static content. So one usually enables the
    #     exportation for CGI and SSI requests only.
    #   o StrictRequire:
    #     This denies access when "SSLRequireSSL" or "SSLRequire" applied even
    #     under a "Satisfy any" situation, i.e. when it applies access is denied
    #     and no other module can change it.
    #   o OptRenegotiate:
    #     This enables optimized SSL connection renegotiation handling when SSL
    #     directives are used in per-directory context.
    #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    <FilesMatch "\.(cgi|shtml|phtml|php)$">
            SSLOptions +StdEnvVars
    </FilesMatch>

    #   Notice: Most problems of broken clients are also related to the HTTP
    #   keep-alive facility, so you usually additionally want to disable
    #   keep-alive for those clients, too. Use variable "nokeepalive" for this.
    #   Similarly, one has to force some clients to use HTTP/1.0 to workaround
    #   their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and
    #   "force-response-1.0" for this.
    BrowserMatch ".*MSIE.*" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0

    <Location />
            AuthType Basic
            AuthName "MARTIN's Wiki"
            AuthUserFile /etc/apache2/httpd.auth-basic
            Require valid-user
            ProxyPass http://127.0.0.1:9554/
            ProxyPassReverse http://127.0.0.1:9554/
            SetOutputFilter proxy-html
            ProxyHTMLURLMap http://127.0.0.1:9554/ /
            RequestHeader unset Accept-Encoding
    </Location>

</VirtualHost>
</IfModule>

OBS1: Para páginas em que se deseja acesso mais restrito, é necessário a criação de seções <Location> customizadas, indicando usuários específicos na diretiva Require ao invés de simplesmente valid-user. Como exemplo, para a página "NOME-PAG" pode-se incluir, logo abaixo da seção <Location />:

    <Location /NOME-PAG/>
            AuthType Basic
            AuthName "MARTIN's Wiki"
            AuthUserFile /etc/apache2/httpd.auth-basic
            Require user NOME-USUARIO
            ProxyPass http://127.0.0.1:9554/
            ProxyPassReverse http://127.0.0.1:9554/
            SetOutputFilter proxy-html
            ProxyHTMLURLMap http://127.0.0.1:9554/ /
            RequestHeader unset Accept-Encoding
    </Location>

OBS2: é importante que o valor da diretiva AuthName seja o mesmo em todas as seções <Location> relacionadas a autenticação, para evitar que uma página demande autenticação distinta para páginas que contenham partes de <Location>'s distintos.

Habilitar o virtual host wikimartin-ssl:

sudo a2ensite wikimartin-ssl

Voilà, Nanoki is up and running!

Iniciando Nanoki automaticamente no boot

Logar na máquina-alvo como operador.

Criar um arquivo no diretório /etc/init.d:

sudo vim /etc/init.d/nanoki

Incluir as seguintes linhas:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          nanoki
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Nanoki initscript
# Description:       Initializes Nanoki's wiki
### END INIT INFO

# Author: Antonio Tadeu A. Gomes <atagomes@lncc.br>

# Do NOT "set -e"

# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
LUA_PATH="/home/wikimartin/Nanoki.112/?.lua;;"
DESC="Nanoki's wiki"
NAME=nanoki
DAEMON=/home/wikimartin/lua-5.1.4/bin/lua
DAEMON_ARGS="/home/wikimartin/Nanoki.112/Nanoki.lua /home/wikimartin/Nanoki.112/. 127.0.0.1 9554 forwarded not"
PIDFILE=/var/run/$NAME.pid
SCRIPTNAME=/etc/init.d/$NAME
USER=wikimartin

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Read configuration variable file if it is present
#[ -r /etc/default/$NAME ] && . /etc/default/$NAME
export LUA_PATH

# Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh

# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions

#
# Function that starts the daemon/service
#
do_start()
{
        # Return
        #   0 if daemon has been started
        #   1 if daemon was already running
        #   2 if daemon could not be started
        start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
                || return 1
        start-stop-daemon --start --quiet --background --chuid $USER --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_ARGS \
                || return 2
        # Add code here, if necessary, that waits for the process to be ready
        # to handle requests from services started subsequently which depend
        # on this one.  As a last resort, sleep for some time.
}

#
# Function that stops the daemon/service
#
do_stop()
{
        # Return
        #   0 if daemon has been stopped
        #   1 if daemon was already stopped
        #   2 if daemon could not be stopped
        #   other if a failure occurred
        start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME
        RETVAL="$?"
        [ "$RETVAL" = 2 ] && return 2
        # Wait for children to finish too if this is a daemon that forks
        # and if the daemon is only ever run from this initscript.
        # If the above conditions are not satisfied then add some other code
        # that waits for the process to drop all resources that could be
        # needed by services started subsequently.  A last resort is to
        # sleep for some time.
        start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON
        [ "$?" = 2 ] && return 2
        # Many daemons don't delete their pidfiles when they exit.
        rm -f $PIDFILE
        return "$RETVAL"
}

#
# Function that sends a SIGHUP to the daemon/service
#
do_reload() {
        #
        # If the daemon can reload its configuration without
        # restarting (for example, when it is sent a SIGHUP),
        # then implement that here.
        #
        start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME
        return 0
}

case "$1" in
  start)
        [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
        do_start
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  stop)
        [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
        do_stop
        case "$?" in
                0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
                2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
        esac
        ;;
  #reload|force-reload)
        #
        # If do_reload() is not implemented then leave this commented out
        # and leave 'force-reload' as an alias for 'restart'.
        #
        #log_daemon_msg "Reloading $DESC" "$NAME"
        #do_reload
        #log_end_msg $?
        #;;    
  restart|force-reload)
        #
        # If the "reload" option is implemented then remove the
        # 'force-reload' alias
        #
        log_daemon_msg "Restarting $DESC" "$NAME"
        do_stop
        case "$?" in
          0|1)
                do_start
                case "$?" in
                        0) log_end_msg 0 ;;
                        1) log_end_msg 1 ;; # Old process is still running
                        *) log_end_msg 1 ;; # Failed to start
                esac
                ;;
          *)
                # Failed to stop
                log_end_msg 1
                ;;
        esac
        ;;
  *)
        #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
        exit 3
        ;;
esac
:

Referenciar script acima nos diretórios de inicialização dos runlevels:

sudo chmod +x /etc/init.d/nanoki
sudo update-rc.d nanoki defaults 99