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
.
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 desudo
, 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
encurses
para Lua compilar corretamente. Com o comandoapt-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 (tampoucorequire"zlib"
já no interpretador Lua).OBS2: pode ser necessária a instalação da biblioteca
zlib
para o lzlib compilar corretamente. Com o comandoapt-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 arquivo
martin-header-en-long.png
no diretório~/Nanoki-?.?.?/etc
!
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 diretivaRequire
ao invés de simplesmentevalid-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
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