<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
Para poder aceder à Internet usando o modem GPRS incorporado em grande parte dos telemóveis modernos, é necessário usar a seguinte //string// de inicialização:
{{{
+CGDCONT=1,"IP","<APN>"
}}}
No caso da Optimus, o APN é {{{internet}}}, pelo que a //string// fica...
{{{
+CGDCONT=1,"IP","INTERNET"
}}}
Depois, é só usar {{{*99***1#}}} como número de telefone na ligação, com os dados {{{username}}} e {{{password}}} em branco.

!!Referências
* [[The Tao of Mac - GSM AT Commands|http://the.taoofmac.com/space/AT%20Commands]]
Em primeiro lugar é necessário configurar o Apache para escutar na porta 443, editando o ficheiro {{{/etc/apache2/ports.conf}}} e adicionando a linha...
{{{
Listen 443
}}}
O suporte para ligações seguras é fornecido pelo {{{mod_ssl}}}. Para activar este módulo é necessário criar o //symlink// apropriado na directoria {{{/etc/apache2/mods-enabled}}}. Isto pode fazer-se de forma mais simples com o comando...
{{{
$ a2enmod ssl
}}}
Precisamos também de um certificado, portanto vamos começar por criar um certificado auto-assinado. Corremos então os comandos seguintes, respondendo às perguntas que o {{{openssl}}} colocar...
{{{
$ mkdir /etc/apache2/ssl
$ cd /etc/apache2/ssl
$ openssl req -new -x509 -days 365 -nodes -out apache.pem -keyout apache.pem
$ chmod 0600 apache.pem
}}}
A seguir, cria-se uma cópia da configuração do site //default//, que iremos alterar para criar um novo site //default// com SSL...
{{{
$ cd /etc/apache2/sites-available
$ cp default default-ssl
}}}
No ficheiro {{{default-ssl}}} substituimos a porta 80 pela porta 443, activamos o suporte SSL e indicamos onde se encontra o nosso certificado...
{{{
NameVirtualHost *:443
<VirtualHost *:443>
    SSLEngine On
    SSLCertificateFile /etc/apache2/ssl/apache.pem
    ...
</VirtualHost>
}}}
Agora, activamos o site {{{default-ssl}}}...
{{{
$ a2ensite default-ssl
}}}
Para finalizar, reiniciamos o Apache...
{{{
$ /etc/init.d/apache2 restart
}}}

!!Nota
O Apache apenas permite a existência de ''um único'' [[virtual-host|Configurar virtual-hosts no Apache]] SSL para cada par {{{endereço:porta}}}. Ou seja, a configuração acima não permite a existência de qualquer outro virtual-host SSL na porta ''443'', uma vez que está acessível a partir de ''todos'' os endereços IP configurados na máquina. Os virtual-hosts SSL não podem ser diferenciados apenas pelo //hostname//.

Assim, é possível existirem duas configurações com SSL...
* {{{<VirtualHost *:443>}}} e {{{<VirtualHost *:8443>}}}
* {{{<VirtualHost 192.168.0.1:443>}}} e {{{<VirtualHost 192.168.0.2:443>}}}
...mas não é possível existir...
* {{{<VirtualHost *:443>}}} juntamente com {{{<VirtualHost 192.168.0.1:8443>}}}
* {{{<VirtualHost *:443>}}} (//www.example.com//) juntamente com {{{<VirtualHost *:443>}}} (//www2.example.com//)
Por //default// o Apache não permite o uso de ficheiros {{{.htaccess}}} dentro da {{{DocumentRoot}}}. Isto pode tornar vulneráveis algumas aplicações web que necessitem desta funcionalidade para proteger directorias sensíveis (o [[dokuwiki|http://wiki.splitbrain.org/wiki:dokuwiki]], por exemplo).

Para alterar este comportamento, activar a directiva:
{{{
AllowOverride All
}}}
...dentro do bloco adequado no ficheiro de configuração do Apache.
Para evitar que o módulo {{{pcnet32}}} capture a placa de rede antes do módulo {{{vmxnet}}}, é preciso que este último seja carregado o mais cedo possível, pelo {{{initrd}}}.

Em primeiro lugar, adicionar o seguinte ao ficheiro {{{/etc/initramfs-tools/modules}}}:
{{{
# Override "pcnet32"...
vmxnet
}}}
Em seguida, é necessário regenerar o {{{initrd.img}}} do kernel que está activo actualmente, correndo...
{{{
$ update-initramfs -u -k $(uname -r)
}}}
Para confirmar que tudo ficou a funcionar, reiniciar a máquina virtual. Depois, como {{{root}}}, fazer...
{{{
$ rmmod pcnet32
$ ping www.google.com
}}}
Se tudo estiver bem, a remoção do módulo {{{pcnet32}}} não terá qualquer efeito e o {{{ping}}} funcionará correctamente.
Este é o meu wiki pessoal com dicas e notas relacionadas com administração de sistemas. A ideia é documentar processos e comandos para que eu não tenha de os saber de cabeça mas, sempre que possível, tentarei contextualizar as entradas para que possam ser úteis para outros, e não apenas para mim.

Sintam-se à vontade para navegar.

//PS: Este wiki tem um [[feed RSS|index.xml]].//
!!Problema 1 (balanceamento de carga)
Temos várias máquinas em //cluster// com um //load balancer// à frente. O //load balancer// responde num endereço {{{10.0.0.2}}} (endereço do //cluster//) e reencaminha o tráfego para uma das máquinas //backend// fazendo //forward// dos pacotes, sem alterar o endereço IP. Neste caso, para estas máquinas não rejeitarem os pacotes, têm de ter o endereço de //cluster// configurado como //alias// numa das suas interfaces (normalmente no //loopback//). Se não fizermos nada, cada uma delas vai assumir o endereço como seu e responder a pedidos ARP, e aí temos confusão...
!!Solução
Em cada uma das máquinas //backend// configuramos o endereço do //cluster// e bloqueamos os pedidos ARP com...
{{{
$ ip addr add 10.0.0.2/32 label lo:0 dev lo
$ arptables -F
$ arptables -A IN -d 10.0.0.2 -j DROP
}}}
Como salvaguarda para o caso das máquinas lançarem acidentalmente pedidos ARP na rede com o endereço de //cluster//, fazemos ainda...
{{{
$ arptables -A OUT -s 10.0.0.2 -j mangle --mangle-ip-s $IP_ADDRESS
}}}
Onde {{{$IP_ADDRESS}}} é o endereço real da máquina.

!!Problema 2 (máquina invisível)
Suponhamos agora que temos uma máquina a capturar tráfego na rede e queremos que ela esteja completamente invisível aos utilizadores. No entanto, também queremos que esteja acessível a partir da máquina do administrador de rede.
!!Solução
Na máquina que queremos que seja invisível bloqueamos ''todos'' os pedidos ARP e configuramos estaticamente o endereço MAC da máquina do administrador:
{{{
$ arptables -F
$ arptables -A IN -j DROP
$ arptables -A OUT -j DROP
$ ip neigh add $ADMIN_BOX_IP lladdr $ADMIN_BOX_MAC nud permanent dev eth0
}}}
Adicionalmente, se quisermos que esta máquina consiga resolver nomes por DNS, configuramos também o endereço MAC do servidor DNS:
{{{
$ ip neigh add $DNS_SRV_IP lladdr $DNS_SRV_MAC nud permanent dev eth0
}}}
Para que a máquina do administrador de rede consiga iniciar ligações para a máquina invisível, temos de configurar lá o endereço MAC desta...
{{{
$ ip neigh add $INVISIBLE_IP lladdr $INVISIBLE_MAC nud permanent dev eth0
}}}

!!Nota
Os comandos //arptables// indicados acima funcionam em RHEL 5. Noutras distribuições (ex: Debian 4.0) poderá ter de usar-se {{{INPUT/OUTPUT}}} em vez de {{{IN/OUT}}}. Para verificar quais os nomes correctos, basta correr o comando {{{arptables -L}}}.
Em primeiro lugar é necessário criar uma //chain// para albergar as regras que iremos criar...
{{{
$ iptables -N in_block_world
}}}

Se a máquina em causa é uma firewall/gateway, então é possível proteger globalmente o serviço SSH. Ou seja, o ataque a uma máquina impede o atacante de tentar ligar-se a qualquer uma das outras máquinas.

No caso de uma firewall/gateway, usam-se as regras indicadas a seguir tal com estão. Se a máquina for um simples servidor, então basta usar a regra {{{INPUT}}}...
{{{
$ iptables -A INPUT   -i "${world_iface}" --match state --state NEW -j in_block_world
$ iptables -A FORWARD -i "${world_iface}" --match state --state NEW -j in_block_world
}}}

//Se não está a usar um kernel 2.6.15 ou mais recente, salte para a secção "Linux 2.6.14 e anteriores", mais abaixo.//

Agora a parte realmente interessante... Usando o módulo {{{ipt_recent}}} podemos dizer que um cliente que tente efectuar mais de 3 ligações no espaço de 30 segundos, vê as suas ligações descartadas imediatamente e durante os 30 segundos após a última tentativa de ligação...
{{{
$ iptables -A in_block_world --proto tcp --dport ssh --match recent --name SSH --set
$ iptables -A in_block_world --proto tcp --dport ssh --match recent --name SSH --update \
                                                     --seconds 30 --hitcount 4 -j DROP
}}}
!!!Nota:
Nas regras acima, {{{--hitcount 4}}} pode ser lido como "começa a bloquear no momento da quarta tentativa de ligação".

!!Linux 2.6.14 e anteriores...
No kernel 2.6.14 e anteriores, o módulo {{{ipt_recent}}} não deve ser usado, pois tem um bug grave que faz com que todas as ligações SSH comecem a ser bloqueadas a partir do momento em que a variável {{{jiffies}}} //dá a volta//, o que acontece ao fim de 25 dias para um kernel 2.6.x ou 250 dias para um kernel 2.4.x.

Neste caso existe uma alternativa, o módulo {{{ipt_hashlimit}}}, que permite (entre outras coisas) impor limites aos ritmos de ligação por endereço de origem.

Usando este módulo, as regras serão...
{{{
$ iptables -A in_block_world --proto tcp --dport ssh \
                             --match hashlimit --hashlimit-name SSH \
                             --hashlimit-mode srcip --hashlimit 5/min --hashlimit-burst 1 \
                             --hashlimit-htable-expire 600000 -j RETURN
$ iptables -A in_block_world --proto tcp --dport ssh -j DROP
}}}
Cada cliente terá direito a um ritmo de 5 ligações por minuto, com duas ligações consecutivas ({{{hashlimit-burst}}} + 1). Uma vez excedidos estes limites todas as novas ligações são bloqueadas durante algum tempo.

!!!Nota:
Ao contrário do {{{ipt_recent}}}, o módulo {{{ipt_hashlimit}}} não usa as tentativas de ligação bloqueadas para prolongar o tempo de bloqueio, o que o pode tornar menos eficaz.
A IBM apenas suporta o DB2 nas distribuições enterprise da Red Hat e SUSE, pelo que são necessários alguns procedimentos manuais para instalar o //runtime client// em distribuições que não usam {{{rpm}}}, como a Debian.

O primeiro passo é importar o //runtime client// a partir do  [[site da IBM|http://www-1.ibm.com/support/docview.wss?rs=71&uid=swg21256051]]. Não é necessário ter um CD original, os //fix packs// também permitem fazer uma instalação de raíz. Neste caso vamos usar o DB2 8.1 FixPak 14 (FP14) para sistemas de 32bit.

Excepto indicação em contrário, todos os passos seguintes deverão ser efectuados como utilizador {{{root}}}.

{{{
$ mkdir /tmp/DB2-FP14
$ cd /tmp/DB2-FP14
$ wget ftp://ftp.software.ibm.com/ps/products/db2/fixes2/english-us/db2linux2632/client/runtime/FP14_MI00176_RTCL.tar
}}}

As únicas dependências explícitas são a //korn shell// (para correr o //script// de instalação) e uma versão da {{{libstdc++}}} anterior à versão instalada por omissão no Debian 4.0 (etch). Para evitar problemas, não vamos optar pela conversão dos {{{.rpm}}} para {{{.deb}}}, pelo que o {{{rpm}}} também tem de ser instalado...
{{{
$ aptitude install ksh libstdc++5 rpm
}}}

Como a base de dados do {{{rpm}}} está em branco, temos de forçar a instalação dos pacotes sem verificação de dependências ({{{--nodeps}}}). Para isso, criamos um //script// que irá invocar o {{{rpm}}} com os parâmetros necessários. Como a directoria {{{/usr/local/bin}}} aparece primeiro na {{{$PATH}}} do {{{root}}}, este //script// pode ser criado lá (como {{{/usr/local/bin/rpm}}}), evitando mexer no verdadeiro {{{rpm}}}:
{{{
#!/bin/bash

if [ "$1" == "-ivh" ]; then
        shift
        /usr/bin/rpm -ivh --nodeps "$@"
else
        /usr/bin/rpm "$@"
fi
}}}
Tornar este ficheiro executável...
{{{
$ chmod +x /usr/local/bin/rpm
}}}

Em Red Hat, ou SUSE, usar-se-ia o instalador gráfico ({{{db2setup}}}) e este faria todo o trabalho de instalação e configuração, mas aqui teremos de usar o instalador de texto ({{{db2_install}}}), que deixa algumas configurações por fazer...
{{{
$ cd /tmp/DB2-FP14
$ tar xf FP14_MI00176_RTCL.tar
$ cd rtcl
$ ./db2_install 
}}}

Após terminado o processo acima, criar uma instância do DB2 (e respectivos utilizadores)...
{{{
$ groupadd db2iadm1
$ groupadd db2fadm1

$ useradd -g db2iadm1 -m -d /home/db2inst1 db2inst1
$ useradd -g db2fadm1 -m -d /home/db2fenc1 db2fenc1

$ /opt/IBM/db2/V8.1/instance/db2icrt -u db2fenc1 db2inst1
}}}

Ao contrário de outras SGBDs, para aceder a uma base de dados remota em DB2 é necessário registá-la no catálogo local...
{{{
$ su - db2inst1
$ db2 catalog tcpip node <server_alias> remote <server> server 50000
$ db2 catalog database <db> as <db_alias> at node <server_alias>
}}}
Os comandos acima assumem que o servidor estará à escuta na porta {{{tcp/50000}}}, o que é o normal.

Antes de fazer {{{exit}}} para voltar ao utilizador {{{root}}}, convém verificar que tudo está a funcionar normalmente. Para isso, deveremos fazer uma //query// à base de dados. Neste caso vamos apenas listar as tabelas:
{{{
$ db2 connect to <db_alias> user <username> using <password>
$ db2 list tables
$ db2 terminate
}}}

Para que qualquer utilizador da máquina possa ligar-se à base de dados remota, é preciso acrescentar as linhas seguintes ao ficheiro {{{/etc/profile}}}:
{{{
if [ -f /home/db2inst1/sqllib/db2profile ]; then
        . /home/db2inst1/sqllib/db2profile
        export PATH="${PATH}:/opt/IBM/db2/8.1/bin"
fi
}}}
Ou, para quem usar //shells// derivadas da {{{csh}}}:
{{{
$ ln -s /home/db2inst1/sqllib/db2cshrc /etc/csh/login.d/
}}}

Para terminar, podemos remover o //script// {{{/usr/local/bin/rpm}}} para que tudo fique como estava inicialmente.
A última versão do cliente de backup do Tivoli Storage Manager para Linux pode ser obtida no [[site da IBM|http://www-306.ibm.com/software/sysmgmt/products/support/IBMTivoliStorageManager.html]]. Neste caso, iremos usar a [[versão 5.5.0.1|http://www-1.ibm.com/support/docview.wss?rs=663&context=SSGSG7&dc=D400&uid=swg24017697&loc=en_US&cs=utf-8&lang=en]] (que funciona perfeitamente com servidores de versões mais antigas, se tal for necessário).

Para começar, vamos precisar do {{{rpm}}} e de algumas bibliotecas de compatibilidade:
{{{
$ aptitude install rpm libstdc++5
}}}

Depois, descomprimimos e instalamos o cliente TSM. Neste passo é preciso ter atenção ao facto do pacote descomprimir directamente para a directoria corrente, pelo que convém fazê-lo numa directoria vazia:
{{{
$ mkdir tsm
$ cd tsm
$ tar xvf ../5.5.0.1-TIV-TSMBAC-LinuxX86.tar
$ rpm -Uvh --nodeps TIVsm-API.i386.rpm TIVsm-API.i386.rpm
}}}

Por alguma razão os ficheiros de localização não são correctamente instalados, pelo que o cliente ({{{dsmc}}}) retornará este erro:
{{{
$ /opt/tivoli/tsm/client/ba/bin/dsmc
ANS0101E Unable to open English message repository 'dsmclientV3.cat'.
}}}
A solução é simples, basta criar o //symlink// que está em falta...
{{{
$ cd /opt/tivoli/tsm/client/ba/bin
$ ln -s ../../lang/en_US en_US
$ ln -s ../../lang/en_US pt_BR
}}}
O segundo //symlink// (pt_BR) evita que o cliente //web// se queixe da falta dos ficheiros de localização para português do Brasil (que estão disponíveis em formato {{{rpm}}} no site da IBM, se os quisermos instalar).

O passo seguinte é a configuração do cliente. Na directoria {{{/opt/tivoli/tsm/client/ba/bin}}} criamos o ficheiro {{{dsm.opt}}} com o seguinte conteúdo:
{{{
SErvername TSM
}}}
E também um ficheiro {{{dsm.sys}}} contendo:
{{{
SErvername  TSM
   COMMmethod         TCPip
   TCPPort            1500
   TCPServeraddress   tsmserver.example.com

NODename LINUXBOX1

PASSWORDACCESS  GENERATE

SCHEDLOGNAME            /var/log/tsm/dsmsched.log
SCHEDLOGRETENTION       15
ERRORLOGNAME            /var/log/tsm/dsmerror.log
ERRORLOGRETENTION       15

COMPRESSIon Yes
}}}
Como é óbvio, o conteúdo acima deverá ser alterado de forma a reflectir a configuração do servidor em causa. No entanto, convém notar três coisas:
* Em ambos os ficheiros de configuração, //servername// é o nome atribuído ao serviço Tivoli que queremos usar, não o nome da máquina onde este está a correr;
* O //nodename// pode ser omitido se o cliente estiver registado no servidor com um nome igual ao //output// do comando {{{hostname}}};
* A directoria {{{/var/log/tsm}}} tem de ser criada à mão.

Assumindo que a máquina cliente já está configurada correctamente do lado do servidor, podemos verificar se tudo está a funcionar listando (por exemplo) as //tapes// disponíveis:
{{{
$ /opt/tivoli/tsm/client/ba/bin/dsmadmc
> q vol
}}}

Se ocorrer um erro relacionado com a falta da biblioteca {{{libgpfs.so}}}, criamos um ficheiro {{{/etc/ld.so.conf.d/tsm-client.conf}}} contendo:
{{{
/opt/tivoli/tsm/client/api/bin
}}}
...e corremos o comando {{{ldconfig}}}.

Para poder controlar o calendário de backups a partir do servidor, e para que o cliente //web// esteja disponível (em {{{http://localhost:1581}}}), é necessário colocar o agente a correr:
{{{
$ /opt/tivoli/tsm/client/ba/bin/dsmcad
}}}
Para que isto aconteça automaticamente no arranque da máquina, acrescentamos ao ficheiro {{{/etc/rc.local}}}:
{{{
# Tivoli Storage Manager
if [ -x /opt/tivoli/tsm/client/ba/bin/dsmcad ]; then
        echo "Starting TSM agent service..."
        /opt/tivoli/tsm/client/ba/bin/dsmcad
fi
}}}

Agora, experimentamos fazer backup de um ficheiro:
{{{
$ /opt/tivoli/tsm/client/ba/bin/dsmc incremental <ficheiro>
}}}
Será necessário fazer //login// (com o utilizador definido para o cliente, que poderá ser o utilizador de administração do Tivoli, ou não), mas isto apenas acontece da primeira vez que este comando é executado.

Usar sempre o caminho completo nos comandos não é simpático, pelo que acrescentamos ao ficheiro {{{/etc/profile}}}:
{{{
#
# Tivoli Storage Manager Client
#
if [ -d /opt/tivoli/tsm/client/ba/bin ]; then
        export PATH="${PATH}:/opt/tivoli/tsm/client/ba/bin"
fi
}}}

!!Nota
Sempre que for instalada uma nova versão do cliente TSM é necessário criar novamente os //symlinks// para os ficheiros de localização/tradução. Isto é verdade inclusivamente em distribuições baseadas em {{{rpm}}}, como o Red Hat Enterprise Linux.
Para activar a colorização de ficheiros de configuração terminados em {{{.conf}}}, criar um ficheiro {{{$HOME/.joerc}}} com o seguinte conteúdo:
{{{
:include /etc/joe/joerc

 Configuration File
*.conf
-autoindent
-syntax conf
}}}
!!Componentes
O serviço NFS é composto por vários //daemons//...
* {{{rpc.nfsd}}} - o servidor NFS propriamente dito (implementado no //kernel//).
* {{{rpc.lockd}}} - gestão de //locks// (implementado no //kernel//).
* {{{rpc.mountd}}} - gestão de //mounts//.
* {{{rpc.statd}}} - parte do mecanismo de //locking//: notifica os clientes em caso de //crash// e //reboot// do servidor.
* {{{rpc.rquotad}}} - suporte para quotas remotas.
Todos estes //daemons// escutam em portas aleatórias indicadas pelo {{{portmap}}}, excepto o {{{rpc.nfsd}}}, que escuta sempre na porta ''2049''. No entanto, todos eles aceitam um parâmetro para determinar a porta onde deverão ficar à escuta.

!!Configuração (Debian)
Para o {{{rpc.mountd}}}, modificar a variável {{{RPCMOUNTDOPTS}}} no ficheiro {{{/etc/default/nfs-kernel-server}}}:
{{{
RPCMOUNTDOPTS="--port 2051"
}}}

Para o {{{rpc.statd}}}, modificar a variável {{{STATDOPTS}}} no ficheiro {{{/etc/default/nfs-common}}}:
{{{
STATDOPTS="--port 2052"
}}}

Para o {{{rpc.rquotad}}}, acrescentar a variável {{{RPCRQUOTADOPTS}}} ao ficheiro {{{/etc/default/quota}}}:
{{{
# Options for rpc.rquotad
RPCRQUOTADOPTS="--port 2053"
}}}

O {{{rpc.lockd}}} é um módulo de //kernel//, portanto é necessário (por exemplo) criar um ficheiro {{{/etc/modprobe.d/nfs}}} com o seguinte conteúdo:
{{{
# Force the NFS lock manager to always use the same port...
options lockd nlm_udpport=2050 nlm_tcpport=2050
}}}

Para que estas definições se tornem efectivas é necessário parar os serviços NFS ({{{nfs-common}}}, {{{nfs-kernel-server}}}, {{{quotarpc}}}), remover os módulos do //kernel// ({{{nfsd}}}, {{{lockd}}}), e iniciar os serviços novamente.

Para verificar que tudo está configurado correctamente, correr...
{{{
$ rpcinfo -p
}}}
Os serviços {{{rpc.statd}}} e {{{rpc.lockd}}} aparecem identificados como {{{status}}} e {{{nlockmgr}}} respectivamente.

!!Firewall
Com os serviços à escuta em portas fixas, torna-se mais fácil configurar uma //firewall//. No entanto, os clientes podem estar à escuta em portas abaixo de 1024, e a //firewall// tem de levar isto em conta.

Usando o [[FireHOL|http://firehol.sourceforge.net]], a configuração para o NFS ficará (no ficheiro {{{/etc/firehol/firehol.conf}}}):
{{{
server custom nfs "tcp/2049:2053 udp/2049:2053" "500:65535" accept
}}}

!!Referências
Para mais detalhes ver o documento [[Linux NFS-HOWTO: Security and NFS|http://nfs.sourceforge.net/nfs-howto/security.html#FIREWALLS]]
Se o Windows teimar em colocar uma drive IDE em modo PIO, mesmo quando a definição "DMA if available" está activa, é necessário abrir o {{{regedit}}} e remover as seguintes chaves:
{{{
HKEY_LOCAL_MACHINE
  +-SYSTEM
    +-CurrentControlSet
      +-Control
        +-Class
          +-{4D36E96A-E325-11CE-BFC1-08002BE10318}
            +-0001
              +-MasterIdDataChecksum
              +-SlaveIdDataChecksum
            +-0002
              +-MasterIdDataChecksum
              +-SlaveIdDataChecksum
}}}
A Microsoft não fornece nenhuma forma fácil de remover completamente o //Windows Messenger// (a versão que vem incluída no Windows), mas é possível fazê-lo:

Abrir uma linha de comandos, ou fazer ''Start → Run'', e executar:
{{{
Rundll32 advpack.dll,LaunchINFSection %windir%\INF\msmsgs.inf,BLC.Remove
}}}
Após esta operação, as funcionalidades dependentes do //Windows Messenger// -- como a assistência remota -- ''deixam de funcionar''. Isto acontece mesmo que o //Windows Live Messenger// esteja instalado.
Em algumas situações será necessário compilar um kernel personalizado (por exemplo, para contornar o [[problema do atraso incontrolável do relógio do sistema|Problemas de sincronização do relógio dentro do VMware (Linux 2.6.x)]], quando a correr numa máquina virtual do vmware), o que deverá ser feito seguindo os passos seguintes...

!!Na primeira vez...
Fazer login como {{{root}}} e instalar os pacotes necessários:
{{{
$ aptitude install fakeroot kernel-package libncurses5-dev kernel-source-2.6.8
}}}
Depois adicionar um utilizador normal ao grupo {{{src}}} (para se poder fazer todo o trabalho sem privilégios de //root//):
{{{
$ adduser carlos src
}}}

!!Gerar os pacotes...
Fazer login com um utilizador pertencente ao grupo {{{src}}} e preparar a //source// do kernel:
{{{
$ cd /usr/src
$ tar jxvf kernel-source-2.6.8.tar.bz2
$ ln -s kernel-source-2.6.8 linux
}}}
Obter a configuração do kernel actual:
{{{
$ cd /usr/src/linux
$ cp /boot/config-2.6.8 .config
}}}
Fazer as alterações necessárias à configuração do kernel, com {{{make menuconfig}}} ou {{{make xconfig}}}. Nesta fase convém guardar o ficheiro {{{.config}}} resultante para poder ser utilizado mais tarde.

Preparar a configuração:
{{{
$ make oldconfig            # para importar as definições contidas no ficheiro ".config"
$ fakeroot make-kpkg clean
}}}
Gerar o novo kernel e os seus //headers// (o parâmetro {{{--append-to-version}}} pode levar outra coisa qualquer.):
{{{
$ fakeroot make-kpkg --initrd --append-to-version=-k8-vmware-cr5 kernel_image kernel_headers
}}}
Terminada a compilação, podemos deixar o código num estado que nos permita compilar módulos externos para este kernel fazendo...
{{{
$ make clean
$ make prepare
}}}

!!Instalar o novo kernel...
Fazer login como "root" e instalar os pacotes gerados:
{{{
$ cd /usr/src
$ dpkg -i kernel_image-[...].deb kernel_headers-[...].deb
}}}
É necessário impedir que o ''apt-get/aptitude'' actualize estes pacotes quando a Debian lançar uma actualização:
{{{
$ echo "kernel-image-2.6.8-k8-vmware-cr5 hold" | dpkg --set-selections
$ echo "kernel-headers-2.6.8-k8-vmware-cr5 hold" | dpkg --set-selections
}}}

!!Para terminar...
Reiniciar a máquina.
Ocasionalmente, pode ser preciso utilizar um pacote que só está disponível numa versão mais recente do Debian, por exemplo, no repositório //testing//. Para o fazer, convém instalar algumas coisas primeiro...
{{{
$ aptitude install debhelper build-essential
}}}
Depois, adicionar o repositório onde se encontram as sources ao ficheiro {{{/etc/apt/sources.list}}}. Por exemplo:
{{{
deb-src http://ftp.linux.pt/pub/mirrors/debian/ testing main
}}}
Sincronizar os repositórios...
{{{
$ aptitude update
}}}
Agora, instalar as dependências de compilação para o pacote em causa:
{{{
$ apt-get build-dep <pacote>
}}}
E compilar...
{{{
$ mkdir ~/build-debs/
$ cd ~/build-debs/
$ apt-get -b source <pacote>
}}}
No final, os ficheiros {{{.deb}}} ficarão na directoria corrente ({{{~/build-debs/}}}) e podem ser instalados fazendo:
{{{
$ dpkg -i <ficheiros>
}}}
Estas instruções têm como base uma UPS da MGE, controlada por USB, mas podem ser usadas com qualquer outra UPS suportada pelo NUT com poucas modificações.

O NUT apresenta uma arquitectura cliente/servidor com vários componentes. Isto permite ter várias máquinas alimentadas por uma única UPS, com uma das máquinas controlando-a directamente, e todas as outras acedendo ao seu estado através da rede. Isto significa que o switch (ou switches) que suporta a rede entre este grupo de máquinas também terá de ser alimentado por alguma UPS, para que a comunicação continue a ser possível no caso de faltar a electricidade.

De uma forma simples, numa situação de falha de electricidade o servidor espera até a UPS entrar em estado crítico (bateria fraca) e notifica as máquinas cliente. Nesta altura, estas iniciam o processo de shutdown e desconectam-se do servidor. Quando a última máquina cliente se desconectar, o servidor começa também a fazer shutdown e, no final, manda a UPS desligar-se. Quando a electricidade voltar a UPS liga-se e as máquinas reiniciam.

Quando o NUT inicia o processo de shutdown (tanto dos clientes como do servidor), a UPS irá desligar-se no final mesmo que a electricidade tenha voltado entretanto. Isto garante que as máquinas não ficam permanentemente desligadas e elimina a necessidade de intervenção manual.

!!No servidor...
Em primeiro lugar é necessário instalar o software...
{{{
$ aptitude install nut nut-usb
}}}

O passo seguinte é configurar o driver da UPS, no ficheiro {{{/etc/nut/ups.conf}}}. Se esta for controlada por USB, não é preciso indicar explicitamente qual é o {{{port}}} que vai ser usado, basta usar {{{auto}}}. Se for uma UPS série, usa-se {{{/dev/ttySx}}}.
{{{
#
# ups.conf
#

[mge]
        driver = newhidups
        port = auto
        desc = "MGE Pulsar Evolution 1100 (rack)"
        offdelay = 30
        ondelay = 120

# EOF - ups.conf
}}}

O {{{upsd}}} é uma peça central do NUT. Ele é o //daemon// responsável pelo controlo da UPS. É ele que fala com o driver e responde aos clientes (locais e remotos).

Definimos então que utilizadores existem, e respectivos direitos, no ficheiro {{{/etc/nut/upsd.users}}}:
{{{
#
# upsd.users
#

[admin]
        password = adminpass
        allowfrom = localhost
        actions = SET
        instcmds = ALL

[mon-master]
        password = masterpass
        allowfrom = localhost
        upsmon master

[mon-slave]
        password = slavepass
        allowfrom = somemachine anothermachine
        upsmon slave

# EOF - upsd.users
}}}
A secção {{{mon-master}}} refere-se à máquina que controla a UPS, enquanto a secção {{{mon-slave}}} se refere aos clientes remotos. Se não existirem clientes remotos, esta secção pode ser omitida, bem como as linhas a ela associadas no ficheiro {{{/etc/nut/upsd.conf}}} que se segue...
{{{
#
# upsd.conf
#

ACL all 0.0.0.0/0
ACL localhost 127.0.0.1/32
ACL somemachine 10.0.0.1/32
ACL anothermachine 10.0.0.2/32

ACCEPT localhost somemachine anothermachine
REJECT all

# EOF - upsd.conf
}}}

O {{{upsmon}}} é a última peça que é necessário configurar. Este //daemon// correrá em todas as máquinas interessadas em obter notificações acerca do estado da UPS (p.ex. o aviso de que a bateria está fraca e é preciso fazer shutdown imediatamente).

No servidor, o conteúdo do ficheiro {{{/etc/nut/upsmon.conf}}} será...
{{{
#
# upsmon.conf
#

MONITOR mge@localhost 1 mon-master masterpass master

MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 20
POWERDOWNFLAG /etc/killpower
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 15

NOTIFYFLAG ONLINE   SYSLOG
NOTIFYFLAG ONBATT   SYSLOG
NOTIFYFLAG LOWBATT  SYSLOG+WALL
NOTIFYFLAG FSD      SYSLOG+WALL
NOTIFYFLAG COMMOK   SYSLOG
NOTIFYFLAG COMMBAD  SYSLOG
NOTIFYFLAG SHUTDOWN SYSLOG+WALL
NOTIFYFLAG REPLBATT SYSLOG
NOTIFYFLAG NOCOMM   SYSLOG

# EOF - upsmon.conf
}}}

Agora é preciso editar o ficheiro {{{/etc/default/nut}}} para que os serviços possam arrancar...
{{{
# start upsd
START_UPSD=yes

# start upsmon
START_UPSMON=yes

...
}}}

Para finalizar, é preciso garantir que os ficheiros de configuração têm as permissões certas...
{{{
$ chown root:nut /etc/nut/*
$ chmod 0640 /etc/nut/*
}}}

!!Nos clientes remotos...

Os clientes remotos apenas precisam de correr o {{{upsmon}}}, com uma configuração deste género...
{{{
#
# upsmon.conf
#

MONITOR mge@upsserver 1 mon-slave slavepass slave

MINSUPPLIES 1
SHUTDOWNCMD "/sbin/shutdown -h +0"
POLLFREQ 5
POLLFREQALERT 5
HOSTSYNC 15
DEADTIME 20
POWERDOWNFLAG /etc/killpower
RBWARNTIME 43200
NOCOMMWARNTIME 300
FINALDELAY 15

NOTIFYFLAG ONLINE   SYSLOG
NOTIFYFLAG ONBATT   SYSLOG
NOTIFYFLAG LOWBATT  SYSLOG+WALL
NOTIFYFLAG FSD      SYSLOG+WALL
NOTIFYFLAG COMMOK   SYSLOG
NOTIFYFLAG COMMBAD  SYSLOG
NOTIFYFLAG SHUTDOWN SYSLOG+WALL
NOTIFYFLAG REPLBATT SYSLOG
NOTIFYFLAG NOCOMM   SYSLOG

# EOF - upsmon.conf
}}}

Tal como no servidor, é necessário activar os serviços no ficheiro {{{/etc/default/nut}}}, desta vez apenas...
{{{
...

# start upsmon
START_UPSMON=yes

...
}}}

E a questão das permissões...
{{{
$ chown root:nut /etc/nut/*
$ chmod 0640 /etc/nut/*
}}}

!!Para terminar...
Activamos os serviços (no servidor e nos clientes remotos)...
{{{
$ invoke-rc.d nut start
}}}

Se tudo estiver configurado correctamente, podemos executar o seguinte comando no servidor, para obter o estado da UPS...
{{{
$ upsc mge@localhost
}}}
Ou nos clientes remotos...
{{{
$ upsc mge@upsserver
}}}

Para simular um shutdown colectivo, tal como aconteceria se tivesse faltado a electricidade e a UPS tivesse ficado com a bateria fraca, executar o seguinte comando no servidor:
{{{
$ upsmon -c fsd
}}}

!!Extras

A maioria dos drivers permite definir se a UPS se desliga imediatamente no final do processo de shutdown do servidor, ou se se mantém ligada por um (curto) intervalo de tempo. Da mesma forma, permitem também definir se a UPS se liga imediatamente após a electricidade voltar, ou se espera algum tempo (para ignorar flashes temporários). Para testar estas definições sem passar pelo processo de shutdown completo, podemos usar o comando...
{{{
$ upsdrvctl shutdown
}}}
Isto desliga ''todas'' as UPSes controladas pelo servidor, pelo que estas não devem estar a alimentar máquinas enquanto se fazem estas experiências.
Em Debian é bastante fácil configurar virtual-hosts no Apache. Para começar, copia-se a configuração {{{default}}} para servir de base ao novo virtual-host...
{{{
$ cd /etc/apache2/sites-available/
$ cp default www-example-com
}}}
Partindo para a edição do ficheiro {{{www-example-com}}}, começa-se por remover a linha...
{{{
NameVirtualHost *:80
}}}
...uma vez que não podem existir duas directivas {{{NameVirtualHost}}} para a mesma combinação {{{endereço:porta}}} ({{{*:80}}} significa que o virtual-host está acessível através de ''qualquer'' endereço IP configurado na máquina, na porta ''80'').

De seguida, adicionam-se as directivas que permitem que os acessos ao endereço {{{http://www.example.com}}} sejam respondidas pelo virtual-host {{{www-example-com}}} e não pelo virtual-host {{{default}}}. Logo após o início do bloco {{{<VirtualHost *:80>}}}...
{{{
ServerName www.example.com
ServerAlias www
}}}

Altera-se então a directiva {{{DocumentRoot}}} para apontar para a directoria correcta. Por exemplo...
{{{
DocumentRoot /var/www/sites/www-example-com
}}}
Para terminar, alteram-se as restantes directivas {{{Directory}}} de acordo com a {{{DocumentRoot}}} e activa-se o novo virtual-host...
{{{
$ a2ensite www-example-com
$ invoke-rc.d apache2 restart
}}}

''Nota:'' Para os virtual-hosts que irão ser configurados com SSL importa ter em atenção que existem algumas limitações (ver: [[Activar HTTPs no Apache]]).
Os ficheiros {{{.pac}}} permitem configurar automaticamente as definições de //proxy// para qualquer um dos browsers modernos, evitando a necessidade de especificar manualmente os endereços do(s) servidor(es) e quais as máquinas que devem ser acedidas directamente. Adicionalmente, permitem ao administrador de rede alterar estas definições nos clientes sem pedir a intervenção dos utilizadores.

A sintaxe é um subconjunto relativamente simples da linguagem javascript, apenas com algumas funções para tomar decisões baseadas em endereços IP e URLs. O ficheiro seguinte demonstra uma possível configuração...

{{{
//
// proxy.pac - proxy auto-config for the internal LAN at "example.com"
//

function FindProxyForURL(url, host)
{
        // Clients in the "10.1.1.x" network don't need a proxy...
        if (isInNet(myIpAddress(), "10.1.1.0", "255.255.255.0")) return "DIRECT";

        // Addresses without a explicit domain are considered local...
        if (isPlainHostName(host)) return "DIRECT";

        // Local networks...
        if (isInNet(host, "127.0.0.0", "255.0.0.0")) return "DIRECT";
        if (isInNet(host, "10.0.0.0", "255.0.0.0")) return "DIRECT";
        if (isInNet(host, "172.16.0.0", "255.240.0.0")) return "DIRECT";
        if (isInNet(host, "192.168.0.0", "255.255.0.0")) return "DIRECT";

        // Our domain...
        if (shExpMatch(host, "*.example.com")) return "DIRECT";

        // FTP connections don't require a proxy...
        if (shExpMatch(url, "ftp://*")) return "DIRECT";

        // Everything else has to use our proxy server...
        return "PROXY proxy.example.com:8080";
}
}}}

Para terminar, basta colocar este ficheiro num servidor web que possa ser contactado directamente pelos clientes, e pedir aos utilizadores para colocarem o seu endereço (p.ex. {{{http://internal.example.com/proxy.pac}}}) no campo de "configuração automática de proxy" existente no painel de configuração do browser.

De notar que os browsers só consultam este ficheiro ao arrancar.

!!Referências:
* [[Navigator Proxy Auto-Config File Format|http://wp.netscape.com/eng/mozilla/2.0/relnotes/demo/proxy-live.html]]
A forma mais simples de configurar uma firewall em Debian é usar o [[FireHOL|http://firehol.sourceforge.net]] para produzir as regras de {{{iptables}}} automaticamente, juntamente com o {{{ulogd}}} para evitar poluir os //logs// do sistema.

Em primeiro lugar é necessário instalar o {{{firehol}}} e o {{{ulogd}}}:
{{{
$ aptitude install firehol ulogd
}}}
Depois, criar uma configuração simples ({{{/etc/firehol/firehol.conf}}}):
{{{
version 5

FIREHOL_LOG_MODE="ULOG"
FIREHOL_LOG_FREQUENCY="6/minute"
FIREHOL_LOG_BURST="3"

interface eth0 lan
        policy reject
        protection strong 100/sec 50

        server ident reject with tcp-reset
        server icmp accept

        server ssh accept

        client all accept
}}}
Finalmente, é necessário editar o ficheiro {{{/etc/default/firehol}}}, colocar {{{START_FIREHOL=YES}}} e arrancar o serviço:
{{{
$ invoke-rc.d firehol start
}}}
Esta receita refere-se à versão //Etch// do Debian.

Antes de mais, instalar todos os pacotes necessários: [[Software importante numa instalação base do Debian]]

!!Para começar...
* No ficheiro {{{/etc/apt/sources.list}}}, remover as entradas desnecessárias (cd-rom) e adicionar {{{contrib}}} e {{{non-free}}} a todas as restantes entradas.
* Substituir a linha {{{DIR_MODE=0755}}} por {{{DIR_MODE=0700}}} no ficheiro {{{/etc/adduser.conf}}}, para que os novos utilizadores não tenham a área //world readable//.
* O //charset// por omissão passou a ser {{{UTF-8}}}. Se a máquina vai ser utilizada principalmente através de sessões ssh remotas, talvez seja interessante mudá-lo para {{{ISO-8859-1}}} para evitar problemas com as aplicações //curses//...
{{{
$ dpkg-reconfigure locales
}}}

!!Estatísticas e monitorização
* Activar o {{{smartd}}} no ficheiro {{{/etc/default/smartmontools}}}
* Activar a recolha de estatísticas pelo {{{sysstat}}} colocando {{{ENABLED="true"}}} no ficheiro {{{/etc/default/sysstat}}}
* O {{{ulogd}}} gera logs enormes, portanto é necessário adicionar as seguintes linhas ao ficheiro {{{/etc/logrotate.d/ulogd}}}:
{{{
compress
delaycompress
}}}

!!Serviço de SMTP
Por omissão, o //daemon// de SMTP fica configurado para entregar o email localmente. Para permitir encaminhar email para outra máquina, correr...
{{{
$ dpkg-reconfigure exim4-config
}}}
... e responder convenientemente às questões colocadas pelo //wizard//.

Se quisermos que as mensagens geradas pelo sistema sejam encaminhadas para um endereço de email, modificar a linha correspondente ao {{{root}}} no ficheiro {{{/etc/aliases}}}:
{{{
root: mail, admin@example.com
}}}
Assim, para além de ficarem guardadas na //mailbox// do utilizador {{{mail}}}, tal como acontece por omissão, as mensagens são também enviadas para o endereço {{{admin@example.com}}}. Para se poder consultar o email do {{{root}}} sem ter de fazer explicitamente {{{mail -u mail}}}, basta criar um //symlink// na directoria {{{/var/mail}}}:
{{{
$ cd /var/mail
$ ln -s mail root
}}}

!!Serviço NTP
Para configurar o //daemon// de NTP, é necessário editar o ficheiro {{{/etc/ntp.conf}}}.

* Em primeiro lugar, comentar as linhas {{{statistics}}} e {{{filegen}}} para reduzir a quantidade de //logging//.
* Agora, se quisermos usar um servidor NTP local para além dos servidores que a Debian já fornece, adicionar uma linha...
{{{
server my.local.server
}}}

!!Acesso por SSH
Em primeiro lugar, criar um ficheiro {{{/etc/issue.net}}} que não mostre demasiada informação sobre a máquina...
{{{
/*
 |
 | Welcome to <maquina>
 |
 | Authorized access only. All connections are logged.
 | Apenas acesso autorizado. Todas as ligacoes sao registadas.
 |
 */
}}}
Depois, é necessário descomentar a seguinte linha no ficheiro {{{/etc/ssh/sshd_config}}}:
{{{
Banner /etc/issue.net
}}}
Agora é necessário alterar um pouco mais o {{{/etc/ssh/sshd_config}}} para tornar as coisas mais seguras:
{{{
PermitRootLogin no
AllowUsers user1 user2  # ou AllowGroups group1 group2
}}}

!!Configurações da Bash
* Editar os ficheiros {{{.bashrc}}} na //home// do {{{root}}}, na //home// do utilizador criado durante a instalação e na directoria {{{/etc/skel}}} para activar algumas coisas interessantes (como a colorização do {{{ls}}}) e desactivar a //programmable completion//.
* Copiar o ficheiro {{{/etc/skel/.bash_logout}}} para a //home// do {{{root}}}, para que a consola seja limpa ao fazer //logout//.

!!Continuar...
* [[Modificações à configuração de um X recém-instalado (em Debian)]]
* [[Desactivar o suporte para IPv6 em Debian]]
* [[Mais segurança no "sudo"]]
No LVM, as //snapshots// funcionam numa lógica //copy-on-write// e inicialmente não ocupam espaço em disco. No entanto, as necessidades de espaço vão aumentando à medida que o volume lógico original vai sendo alterado (e que a própria //snapshot// vai sendo alterada, se a estivermos a usar em modo //read-write//). Por esta razão é necessário especificar o tamanho máximo que poderão atingir. Claramente este valor depende do tipo de utilização dos volumes em causa, e pode até ser bastante reduzido para //snapshots// que irão existir apenas durante um curto período de tempo, mas em geral deverá estar entre 15 e 20% do tamanho do volume original.

''Nota:'' Se o espaço alocado à //snapshot// se esgotar, esta deixa de poder ser utilizada mas o volume lógico original não sofre quaisquer consequências.

Assim, para capturar instantaneamente o estado actual do volume lógico {{{/dev/vg0/lv0}}} para dentro de uma //snapshot// de nome {{{lv0-snap}}}, com um tamanho máximo de 2Gb, faz-se...
{{{
$ lvcreate -L 2G -n lv0-snap -s /dev/vg0/lv0
}}}
''Nota:'' Como se torna óbvio, não é possível criar //snapshots// se o respectivo //volume group// estiver completamente alocado.

A partir daqui a //snapshot// funciona como um volume perfeitamente normal. Ou seja, se contiver um //filesystem// {{{ext3}}} pode ser usada fazendo...
{{{
$ mkdir /mnt/snapshot
$ mount -t ext3 /dev/vg0/lv0-snap /mnt/snapshot
}}}

E quando já não for necessária, pode ser eliminada com:
{{{
$ lvremove -f /dev/vg0/lv0-snap
}}}

!!Sistemas de ficheiros e UUID's
Um //filesystem// contido numa //snapshot// é uma cópia do //filesystem// original, pelo que ambos partilham o mesmo identificador único (UUID). Se isto constitui, ou não, um problema depende do sistema de ficheiros em causa e de estarmos, ou não, a montar //filesystems// por UUID. Em geral, devemos alterar o UUID do //filesystem// contido na //snapshot// sempre que esta não seja descartável a curto prazo e ''sempre'' que o UUID esteja a ser usado para montar o //filesystem// original.

Cada sistema de ficheiros tem um comando diferente para alterar o UUID:
{{{
$ tune2fs -U time /dev/vg0/lv0-snap                 # ext3
$ reiserfstune --uuid $(uuidgen) /dev/vg0/lv0-snap  # reiserfs
$ jfs_tune /dev/vg0/lv0-snap -U time                # jfs
$ xfs_admin -U generate /dev/vg0/lv0-snap           # xfs
}}}

Quanto a montar múltiplos //filesystems// com o mesmo UUID, com {{{ext3}}} ou {{{reiserfs}}} não existe qualquer tipo de problema, mas com {{{xfs}}} é necessário indicar que o UUID do //filesystem// contido na //snapshot// deve ser ignorado:
{{{
$ mount -o nouuid -t xfs /dev/vg0/lv0-snap /mnt/snapshot
}}}

Já com o sistema de ficheiros {{{jfs}}} a restrição é diferente: antes de montar uma //snapshot// é ''sempre'' necessário correr um {{{fsck}}}, mesmo que o seu UUID tenha sido alterado:
{{{
$ jfs_fsck /dev/vg0/lv0-snap
}}}
Criar um utilizador e dar-lhe permissões numa determinada //database// é bastante simples:
{{{
mysql> create user 'utilizador'@'maquina' identified by 'senha';

mysql> create database foobar;
mysql> grant all on foobar.* to utilizador;
mysql> flush privileges;
}}}
Para permitir acesso a partir de qualquer máquina remota, basta colocar {{{'%'}}} no lugar de {{{'maquina'}}}.

!!Nota
Atenção aos caracteres {{{'}}} no comando de criação do utilizador. Tratam-se de duas //strings// separadas por {{{@}}} e não uma única //string// com uma {{{@}}} lá dentro.
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
[[Bem-vindos]]
[[Storage em Linux com LVM]]
[[Expandir ou encolher volumes LVM]]
[[Criar snapshots com o LVM]]
Para definir o editor de texto //default// (usado, por exemplo, quando se invoca o comando {{{visudo}}}) basta fazer:
{{{
$ update-alternatives --config editor
}}}
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
Se a máquina não vai necessitar de suporte para IPv6, este pode ser desactivado da seguinte forma...

!!Kernel 2.6.x
Comentar a seguinte linha no ficheiro {{{/etc/modprobe.d/aliases}}}:
{{{
alias net-pf-10 ipv6
}}}
...e acrescentar...
{{{
alias net-pf-10 off
}}}

!!Kernel 2.4.x
Descomentar a seguinte linha no ficheiro {{{/etc/modutils/aliases}}}...
{{{
# alias net-pf-10 off           # IPv6
}}}
...e de seguida executar o comando:
{{{
$ /sbin/update-modules.modutils
}}}
Para activar a indexação de directorias em ext3, basta fazer:
{{{
$ tune2fs -O dir_index <device>
}}}
A partir daqui as directorias irão sendo indexadas à medida que forem sendo criadas/modificadas. Para que as directorias existentes fiquem também indexadas, é preciso correr o seguinte comando (com o //filesystem// "unmounted"):
{{{
$ fsck.ext3 -f -D <device>
}}}

!!Distribuições recentes
A maioria das distribuições recentes já configura a opção {{{dir_index}}} em todos os //filesystems// ext3 formatados durante a instalação. Se o seguinte comando produzir algum resultado, então a opção está activa:
{{{
$ dumpe2fs <device> | grep dir_index
}}}

!!Extra
A indexação só compensa se a directoria contiver mais de //n// entradas (com //n// escolhido pelo sistema), pelo que nem todas as directorias no //filesystem// farão uso desta funcionalidade. Usando o comando {{{lsattr}}} podemos verificar que directorias estão indexadas: todas as que aparecerem com um atributo "{{{I}}}" associado.
Para que uma instalação Debian consiga enviar e-mail para fora usando um servidor SMTP que força o uso de autenticação necessitamos de, em primeiro lugar, reconfigurar o Exim:
{{{
$ dpkg-reconfigure exim4-config
}}}

Nos painéis de configuração apresentados pelo //debconf//, estas são as opções mais importantes:
* Escolher a opção «//mail sent by smarthost; received via SMTP or fetchmail//» no painel «//General type of mail configuration//»;
* Inserir o nome do servidor de mail que irá fazer //relay// (p.ex: {{{smtp.telepac.pt}}}) no painel «//IP address or host name of the outgoing smarthost//»;
* Responder ''sim'' à questão «//Hide local mail in outgoing mail?//»;
* O passo anterior faz com que os e-emails enviados a partir da máquina local possam ter como remetente {{{user@dominio.valido}}}. A configuração deste domínio faz-se no painel «//Visible domain name for local users//».

Isto seria suficiente para enviar e-mail para fora a partir de, por exemplo, uma rede interna de uma empresa, mas muitos ISPs configuram os seus servidores para negarem o //relay// de e-mail a utilizadores não autenticados, mesmo a partir das suas próprias redes, por questões de segurança.

Sempre que o Exim contactar o servidor {{{smtp.telepac.pt}}} para envio de e-mail, deverá fazer //login// com o utilizador {{{utilizador}}} e password {{{password}}}. Tal consegue-se acrescentando uma linha ao ficheiro {{{/etc/exim4/passwd.client}}}...
{{{
smtp.telepac.pt:utilizador:password
}}}

Se o servidor do ISP só aceita autenticação simples (sem cifra), é ainda preciso criar um ficheiro {{{/etc/exim4/exim4.conf.localmacros}}} contendo a seguinte linha:
{{{
AUTH_CLIENT_ALLOW_NOTLS_PASSWORDS=1
}}}
Para tornar a configuração efectiva, reiniciar o Exim:
{{{
$ invoke-rc.d exim4 restart
}}}

Para verificar que tudo está a funcionar correctamente, experimentar enviar um e-mail para um endereço externo...
{{{
$ echo "corpo da mensagem" | mail alguem@algures.com -s "teste de envio de email externo"
}}}
E, já agora, verificar também que a entrega de e-mail local continua a funcionar...
{{{
$ echo "corpo da mensagem" | mail utilizador -s "teste de envio de email local"
$ mail -u utilizador
}}}

!!Nota
Antes de tentar fazer //login//, o Exim faz um //reverse lookup// ao endereço IP do servidor que está a tentar contactar, e é o resultado desse //reverse lookup// que é pesquisado no ficheiro {{{passwd.client}}}.

Assim, no exemplo da Telepac acima, podemos confimar que o nome {{{smtp.telepac.pt}}} funciona com:
{{{
$ host smtp.telepac.pt
smtp.telepac.pt has address 212.55.154.44
$ host 212.55.154.44
44.154.55.212.in-addr.arpa domain name pointer smtp.telepac.pt.
}}}
Mas no exemplo a seguir já teriamos de usar {{{outmail.example.com}}} em vez de {{{smtp.example.com}}}...
{{{
$ host smtp.example.com
smtp.example.com has address 172.16.1.10
$ host 172.16.1.10
10.1.16.172.in-addr.arpa domain name pointer outmail.example.com.
}}}
Para que o Apache não mostre a sua versão nas páginas de erro, alterar a linha {{{ServerTokens}}} no ficheiro {{{/etc/apache2/apache2.conf}}} para {{{Prod}}} ou {{{ProductOnly}}}:
{{{
ServerTokens Prod
}}}
Um dos principais benefícios do [[LVM|Storage em Linux com LVM]] é a possibilidade de alterar os tamanhos dos volumes sempre que tal seja necessário, incluindo a alteração do espaço disponível nos //volume groups// através da adição ou remoção de discos, sem reiniciar a máquina.

!!Expandir um volume lógico
Como se compreende facilmente, para expandir um volume lógico é necessário que o //volume group// a que pertence tenha espaço disponível. No entanto, o espaço não tem de ser contíguo nem adjacente ao volume lógico a expandir. Posto isto, e como exemplo, para atribuir mais 10Gb ao volume {{{lv0}}} usa-se o comando {{{lvextend}}}:
{{{
$ lvextend -L +10G /dev/vg0/lv0
}}}
Mas isto só aumenta o tamanho do volume lógico. Se este contiver um //filesystem//, é preciso redimensioná-lo também, e a forma de o fazer vai depender do sistema de ficheiros em causa. Se for {{{ext3}}}, basta usar o comando {{{resize2fs}}}, sem necessidade de fazer {{{umount}}}:
{{{
$ resize2fs -p /dev/vg0/lv0
}}}
Para outros sistemas de ficheiros existirá um comando semelhante, ou até algo completamente diferente, como é o caso do {{{jfs}}}:
{{{
$ mount -o resize,remount /dev/vg0/lv0
}}}

!!Encolher um volume lógico
Para reduzir o tamanho de um volume lógico pode usar-se o comando {{{lvreduce}}}. No entanto, é preciso ter em conta que a maioria dos sistemas de ficheiros não suportam a redução de tamanho e os que suportam não o permitem fazer sem um {{{umount}}} prévio.

A título de exemplo, eis como se encolhe um volume lógico {{{lv0}}}, contendo um sistema de ficheiros {{{ext3}}}, de 20Gb para 15Gb...

Para evitar erros nas contas que possam provocar perdas de dados, primeiro encolhemos o //filesystem// para um tamanho inferior ao que terá no final:
{{{
$ umount /mnt/filesystem
$ e2fsck -f /dev/vg0/lv0
$ resize2fs -p /dev/vg0/lv0 12G
}}}
De seguida, reduzimos o volume lógico para a dimensão pretendida:
{{{
$ lvreduce -L -5G /dev/vg0/lv0
}}}
Finalmente, expandimos o //filesystem// para a totalidade do espaço no volume lógico:
{{{
$ resize2fs -p /dev/vg0/lv0
}}}
''Nota:'' Se o volume lógico não contiver um //filesystem//, mas sim um //tablespace// de uma base de dados (por exemplo), a forma mais segura de fazer a redução de tamanho deverá ser semelhante.

!!Alterar o tamanho de um //volume group// (adicionar e remover discos)
Para adicionar um novo disco ao //volume group// {{{vg0}}}, e assim aumentar o espaço disponível para criar ou expandir volumes lógicos, basta correr os comandos seguintes:
{{{
$ pvcreate /dev/sdc1
$ vgextend vg0 /dev/sdc1
}}}
Por outro lado, para remover um disco é preciso mover o espaço nele alocado (volumes lógicos) para outras zonas do //volume group//. Para isto usa-se o comando {{{pvmove}}} e, como é natural, o //volume group// tem de ter espaço livre suficiente para acomodar a migração dos dados...
{{{
$ pvmove -v /dev/sdb1
$ vgreduce vg0 /dev/sdb1
}}}

!!Alterar o tamanho de um //physical volume// (expansão implícita do //volume group//)
Se um //physical volume// tiver aumentado de tamanho (ex: um [[RAID por software|RAID-1 (software) em Linux]] que foi [[expandido|Expandir um array RAID-1 (software) em Linux]]), para que expaço extra fique disponível no //volume group// a que pertence é necessário executar o comando...
{{{
$ pvresize /dev/md0
}}}
Os passos seguintes mostram como se pode expandir um //array// RAID-1 (software) sem perigo de perder dados e minimizando os tempos de espera enquanto os seus componentes se sincronizam. Se os discos forem //hot-swappable//, todas as operações podem ser efectuadas com a máquina em funcionamento e sem reiniciar o sistema.

Tomemos o //array// {{{md0}}}, composto por dois discos de 120Gb com uma partição cada ({{{sdb1}}} e {{{sdc1}}}). Queremos expandir este //array// com dois discos novos de 400Gb.

Em primeiro lugar expulsamos o primeiro disco do //array//:
{{{
$ mdadm --fail /dev/md0 /dev/sdb1
$ mdadm --remove /dev/md0 /dev/sdb1
}}}
Removemos este disco da máquina e colocamos no seu lugar um disco maior. Com o {{{cfdisk}}} (ou outra ferramenta de particionamento) criamos neste novo disco uma partição de tipo //Linux raid autodetect// e adicionamo-la ao //array//:
{{{
$ mdadm --add /dev/md0 /dev/sdb1
}}}
Agora esperamos que o //array// se sincronize, o que poderá demorar bastante tempo. Para observar o progresso podemos fazer {{{cat /proc/mdstat}}}.

Com os dados já replicados no disco novo, expulsamos o segundo disco antigo do //array//:
{{{
$ mdadm --fail /dev/md0 /dev/sdc1
$ mdadm --remove /dev/md0 /dev/sdc1
}}}
Nesta altura já podemos expandir o //array// para o novo espaço disponível, usando o comando:
{{{
$ mdadm --grow --size=max /dev/md0
}}}
Podemos confirmar que o //array// aumentou verificando o número de blocos reportados pelo ficheiro {{{/proc/mdstat}}} ou através do comando {{{mdadm --detail /dev/md0}}}.

Removemos então o segundo disco antigo disco da máquina e colocamos no seu lugar um disco maior. Para este segundo disco já não precisamos de criar a partição manualmente, podemos simplesmente copiar a tabela de partições do primeiro disco (assumindo que os discos são iguais) e adicioná-la ao //array//:
{{{
$ sfdisk -d /dev/sdb | sfdisk /dev/sdc
$ mdadm --add /dev/md0 /dev/sdc1
}}}
Novamente, o //array// inicia a sincronização dos dados para o novo disco. No entanto, desta vez não temos de esperar pelo fim deste processo para o continuar a utilizar.

!!Passos seguintes
Se o //array// tiver um sistema de ficheiros {{{ext3}}} em cima, este pode ser expandido (mesmo sem fazer {{{umount}}}) com o comando:
{{{
$ resize2fs /dev/md0
}}}
Se o //array// estiver integrado num //volume group// [[LVM|Storage em Linux com LVM]] como um //physical volume//, o espaço extra só estará disponível para utilização em volumes lógicos após executado o comando:
{{{
pvresize /dev/md0
}}}

!!Segurança dos dados
A expulsão dos discos antigos do //array// não destrói quaisquer dados, pelo que qualquer um deles (ou ambos) pode ser usado para activar o //array// na sua forma inicial em caso de problemas. Desta forma pode dizer-se que a expulsão do primeiro disco constitui imediatamente um //backup//.

!!Notas
Tal como acontece ao [[criar|RAID-1 (software) em Linux]] um novo //array//, ao colocarmos discos novos convém criar as partições destinadas ao RAID com um tamanho ligeiramente inferior ao do disco físico. Isto permite substituir um disco avariado por outro de um fabricante diferente já que, para um dado tamanho anunciado, discos de fabricantes diferentes podem ter tamanhos reais distintos.
!!Problema
Imaginemos um segmento de rede (ethernet) com endereços da forma {{{192.168.0.0/24}}}, onde o //router// de acesso ao exterior tem o endereço {{{192.168.0.254}}}. Suponhamos também que o //router// é controlado por uma entidade externa (ISP), pelo que não podemos fazer alterações à sua configuração.

Nesta LAN queremos introduzir uma máquina Linux que irá desempenhar um papel de //firewall//, por onde passará todo o tráfego que circula entre o //router// e os //hosts//. Não queremos mudar os endereços dos //hosts//.

Assumimos também que não podemos simplesmente configurar esta //firewall// como uma [[bridge ethernet|http://en.wikipedia.org/wiki/Ethernet_bridge]] (também vai fazer NAT e encaminhamento para uma rede privada composta por várias [[VLANs|VLANs em Debian]], por exemplo).

!!Solução com Proxy ARP (em Debian)
Eis uma configuração de exemplo, definida no ficheiro {{{/etc/network/interfaces}}}:
{{{
#
# interface externa
#
auto eth0
iface eth0 inet static
        address 192.168.0.1
        netmask 255.255.255.0
        broadcast 192.168.0.255
        gateway 192.168.0.254
        ip-proxy-arp 1

        # A unica rota desta interface aponta para o router externo.
        up ip route del 192.168.0.0/24 dev eth0
        up ip route add 192.168.0.254 dev eth0

#
# interface interna
#
auto eth1
iface eth1 inet static
        address 192.168.0.1
        netmask 255.255.255.0
        broadcast 192.168.0.255
        ip-proxy-arp 1
}}}

!!!Notas
# Ambas as interfaces têm o mesmo endereço IP;
# Ambas as interfaces têm o {{{ip-proxy-arp}}} activo;
# Como uma rota para um endereço específico tem sempre precedência sobre uma rota para uma gama de endereços, na interface externa a rota "normal" é substituída por uma rota explícita para o router externo. Isto torna as duas interfaces distintas do ponto de vista do encaminhamento de tráfego:
** Por uma circula o tráfego com destino ao router externo (a nossa //gateway//);
** Por outra circula o tráfego com destino a qualquer outro endereço desta //subnet// (os //hosts//).

!!Para finalizar...
Quando se coloca a //firewall// em produção inicialmente, isto não funciona, porquê?

Enquanto os //hosts// e o //router// tiverem entradas antigas nas suas //caches// ARP, vão sempre tentar contactar-se directamente. À medida que as entradas vão expirando, as coisas vão começando a funcionar.

Para que tudo funcione imediatamente, é necessário convencer toda a "gente" a actualizar as entradas. Para isso usa-se o comando {{{arping}}}, o qual tem de ser instalado:
{{{
$ aptitude install iputils-arping
}}}
De seguida, usa-se o seguinte //script// para actualizar as //caches// todas de uma vez:
{{{
#!/bin/bash
#
# Actualiza a cache ARP das outras maquinas.
#

OLDVAL="$(cat /proc/sys/net/ipv4/ip_nonlocal_bind)"
echo "1" > /proc/sys/net/ipv4/ip_nonlocal_bind

address="0"

echo -n "Updating ARP caches..."
# Excluir o endereco 192.168.0.254 (gateway externa).
while [ "$address" -lt "254" ]; do
        arping -q -I eth0 -c 1 -U -s "192.168.0.${address}" "192.168.0.254"
        arping -q -I eth0 -c 1 -U -s "192.168.0.254" "192.168.0.${address}"

        address="$[$address + 1]"
done
echo "done."

echo "$OLDVAL" > /proc/sys/net/ipv4/ip_nonlocal_bind
}}}

!!Referências
* [[Pseudo-bridges with Proxy-ARP|http://www.linux.com/howtos/Adv-Routing-HOWTO/lartc.bridging.proxy-arp.shtml]]
* [[Proxy ARP with Linux|http://www.sjdjweis.com/linux/proxyarp/]]
Quando se faz login numa sessão X sem passar pelo login na consola, o script {{{/etc/profile}}} não é executado. Por causa disto algumas definições nele contidas não terão efeito (paths extra, etc.).

Para importar as definições contidas no profile global e no profile do utilizador, cria-se um ficheiro {{{/etc/X11/Xsession.d/10profile-hostname}}} com o seguinte conteúdo:
{{{
#
# Import profiles into X session environment
#

[ -f /etc/profile ] && . /etc/profile
[ -f $HOME/.profile ] && . $HOME/.profile
}}}
Em primeiro lugar instale o JDK da Sun conforme descrito aqui: [[Instalação do Sun JDK em Linux (Debian)]]

Agora, faça o download do "tar.gz" a partir do [[site|http://ant.apache.org/]], e descomprima-o na directoria {{{/opt}}}.

Depois adicione o seguinte conteúdo ao fundo do ficheiro {{{/etc/profile}}}, fazendo as modificações necessárias caso esteja a tentar instalar uma versão diferente da 1.7.0:
{{{
# Apache Ant
if [ -d /opt/apache-ant-1.7.0 ]; then
        ANT_HOME="/opt/apache-ant-1.7.0"
        PATH="${PATH}:${ANT_HOME}/bin"

        export ANT_HOME PATH
fi
}}}
Depois de fazer o download da versão apropriada (não-rpm) a partir do [[site|http://java.sun.com]] da Sun, correr o instalador e mover a directoria resultante para dentro da directoria {{{/opt}}}.

Depois adicionar o seguinte conteúdo ao fundo do ficheiro {{{/etc/profile}}}, fazendo as modificações necessárias caso esteja a tentar instalar uma versão diferente do "Java 6.0 update 3":
{{{
# Sun JDK
if [ -d /opt/jdk1.6.0_03 ]; then
        JDK_HOME="/opt/jdk1.6.0_03"
        JAVA_HOME="${JDK_HOME}/jre"
        PATH="${PATH}:${JDK_HOME}/bin:${JAVA_HOME}/javaws"
        MANPATH="${MANPATH}:${JDK_HOME}/man"

        export JAVA_HOME PATH MANPATH
fi
}}}

!!Nota:
Algum software não corre se a variável {{{$JAVA_HOME}}} não estiver declarada, portanto é importante que o {{{/etc/profile}}} seja lido também nos logins via {x,k,g}dm: [[Importar o profile num login X (em Debian)]]
/***
|''Name:''|LegacyStrikeThroughPlugin|
|''Description:''|Support for legacy (pre 2.1) strike through formatting|
|''Version:''|1.0.2|
|''Date:''|Jul 21, 2006|
|''Source:''|http://www.tiddlywiki.com/#LegacyStrikeThroughPlugin|
|''Author:''|MartinBudden (mjbudden (at) gmail (dot) com)|
|''License:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.0|
***/

//{{{
// Ensure that the LegacyStrikeThrough Plugin is only installed once.
if(!version.extensions.LegacyStrikeThroughPlugin) {
version.extensions.LegacyStrikeThroughPlugin = {installed:true};

config.formatters.push(
{
	name: "legacyStrikeByChar",
	match: "==",
	termRegExp: /(==)/mg,
	element: "strike",
	handler: config.formatterHelpers.createElementAndWikify
});

} //# end of "install only once"
//}}}

Se uma conta de um utilizador normal for comprometida (pela password), e esse utilizador tiver direitos para utilizar o {{{sudo}}} indiscriminadamente, para todos os efeitos a conta {{{roo}}}t também fica comprometida. Para que isto não aconteça, basta adicionar (correndo o comando {{{visudo}}})...
{{{
Defaults targetpw
}}}
...ao {{{/etc/sudoers}}} de modo a ser necessária a password do {{{root}}} em vez da password do utilizador.

Isto significa que o utilizador terá de conhecer a password do {{{root}}}, claro.

Em situações onde apenas se queira dar uma acesso {{{root}}} parcial (para executar apenas alguns comandos), isto não é desejável. Nestes casos basta adicionar...
{{{
Defaults:user !targetpw
}}}
... ao {{{/etc/sudoers}}} de modo a que o utilizador {{{user}}} possa usar a sua própria password.
Concatenar um conjunto de ficheiros PDF num só:
{{{
$ gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=output.pdf -dBATCH file1.pdf file2.pdf ... fileN.pdf
}}}
Extraír uma sequência de páginas para um ficheiro separado:
{{{
$ gs -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dFirstPage=m -dLastPage=n -sOutputFile=output.pdf file.pdf
}}}
''Nota:'' Em Windows o Ghostscript é invocado com o comando {{{gswin32}}} em vez de {{{gs}}}.
Em primeiro lugar é necessário configurar a PowerShell para autorizar a execução de //scripts//, o que se consegue com o seguinte comando:
{{{
> Set-ExecutionPolicy RemoteSigned
}}}
Depois, é necessário criar o //script// que será executado sempre que a PowerShell arranca.Este script estará normalmente contido no ficheiro {{{WindowsPowerShell\Microsoft.PowerShell_profile.ps1}}}, dentro da pasta {{{My Documents}}} do utilizador. Para confirmar isto, correr:
{{{
> echo $profile
}}}
Para mudar a //prompt// para uma forma mais próxima daquela usada pelo {{{cmd.exe}}}, usa-se o seguinte código:
{{{
function prompt {
	"$(get-location)> "
}
}}}
Se quisermos algo mais trabalhado, podemos mudar também o título da janela para incluir a directoria corrente:
{{{
function prompt {
	"$(get-location)> "
	$host.UI.RawUI.WindowTitle = "Windows PowerShell - $(get-location)"
}
}}}
A não ser que o rato apenas tenha dois botões, a emulação do botão do meio deve ser desligada para evitar comportamentos esquisitos. No ficheiro {{{/etc/X11/xorg.conf}}}, secção {{{InputDevice}}}:
{{{
Option "Emulate3Buttons" "false"
}}}

Acrescentar uma secção {{{ServerFlags}}} ao {{{/etc/X11/xorg.conf}}}, com os valores a definir para o DPMS:
{{{
Section "ServerFlags"
              Option "BlankTime" "5"
              Option "StandByTime" "10"
              Option "SuspendTime" "15"
              Option "OffTime" "20"
EndSection
}}}

!!Continuar...
* [[X a 96dpi em Debian]]
* [[Importar o profile num login X (em Debian)]]
Abrir o {{{regedit}}} e navegar até à pasta...
{{{
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\11.0\Registration
}}}
Dentro desta pasta existirão outras cujos nomes são //GUID//s, encontrar a que se refere ao Office 2003 examinando o conteúdo das chaves {{{ProductName}}}.

Localizada a pasta correcta, apagar as chaves {{{ProductID}}} e {{{DigitalProductID}}}. Agora, ao correr qualquer uma das aplicações do Office, será pedida uma nova chave.
Numa situação em que existem diversos dispositivos USB idênticos ligados a uma máquina, a ordem pela qual são associados a //devices// na directoria {{{/dev}}} depende da ordem pela qual são ligados. Nestes casos, desligar e voltar a ligar um dispositivo, bem como diferentes ordens de inicialização dos dispositivos após um //reboot//, pode resultar num //device// diferente.

Para evitar depender dos //devices// directamente, podemos usar o {{{udev}}} para criar um //symlink// com um determinado nome, que apontará sempre para o //device// associado ao dispositivo que queremos.

Por exemplo, se tivermos uma máquina fotográfica digital e uma //pen// USB, e uma vez que ambas são reconhecidas como discos, tanto podemos ter a máquina fotográfica como {{{/dev/sda1}}} e a //pen// como {{{/dev/sdb1}}}, como podemos ter o contrário, dependendo de qual dos dispositivos ligamos primeiro.

Para ter a máquina fotográfica sempre acessível através de {{{/dev/mycamera}}}, começamos por a ligar e descobrir qual o //device// que lhe foi atribuído (usando o comando {{{dmesg}}}). Por exemplo, para uma máquina fotográfica da Olympus, poderíamos fazer...
{{{
$ dmesg | grep -A 2 -i olympus
}}}
...e ficaríamos a saber que a máquina ficou associada ao disco {{{sdb}}} a partir do seguinte resultado...
{{{
  Vendor: OLYMPUS   Model: X100,D540Z,C310Z  Rev: 1.00
  Type:   Direct-Access                      ANSI SCSI revision: 02
SCSI device sdb: 512000 512-byte hdwr sectors (262 MB)
}}}
Podemos então obter mais informação acerca do dispositivo ({{{/dev/sdb1}}}) com o objectivo de descobrir algo que o identifique unicamente...
{{{
$ udevinfo -a -p $(udevinfo -q path -n /dev/sdb1)
}}}
O resultado deste comando é uma lista enorme de atributos, mas o que realmente interessa é encontrar o bloco onde aparece a marca e/ou o modelo do dispositivo. No caso da máquina fotográfica acima, seria...
{{{
  looking at parent device '/devices/pci0000:00/0000:00:07.2/usb1/1-1':
    KERNELS=="1-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{serial}=="000365241020"
    ATTRS{product}=="X100,D540Z,C310Z"
    ATTRS{manufacturer}=="OLYMPUS"
    ATTRS{maxchild}=="0"
    ATTRS{version}==" 2.00"
    ATTRS{devnum}=="7"
    ATTRS{speed}=="12"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bcdDevice}=="0100"
    ATTRS{idProduct}=="0105"
    ATTRS{idVendor}=="07b4"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{bmAttributes}=="c0"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bNumInterfaces}==" 1"
}}}
Os atributos {{{manufacturer}}}, {{{product}}} e {{{serial}}} identificam esta máquina fotográfica sem qualquer sombra de dúvida mas, na prática, o atributo {{{serial}}} acaba por ser suficiente, já que é pouco provável que alguém tenha o "azar" de ter dois dispositivos USB diferentes com o mesmo número de série...

Criamos então um ficheiro na directoria {{{/dev/udev/rules.d}}} com as nossas regras (apenas uma, por agora). O nome a dar a este ficheiro dependerá da distribuição, mas terá sempre um prefixo que determinará a sua posição na ordem pela qual o {{{udev}}} interpreta os ficheiros de regras existentes nesta directoria (ordem alfabética). Em Debian podemos chamar-lhe {{{z25_mysymlinks.rules}}}. O seu conteúdo será...
{{{
BUS=="usb", ATTRS{serial}=="000365241020", SYMLINK+="mycamera"
}}}
Para verificar que esta configuração funciona, desliga-se a máquina fotográfica e volta-se a ligar.
{{{
$ ls -l /dev/mycamera
lrwxrwxrwx 1 root root 4 2007-09-09 23:19 /dev/mycamera -> sdb1
}}}
Vemos então que funcionou. A partir de agora podemos ignorar o //device// atribuído à máquina fotográfica e usar {{{/dev/mycamera}}} sempre que for necessário.

!!Referências:
* [[Writing udev rules|http://www.reactivated.net/writing_udev_rules.html]]
<div class='header' macro='gradient vert #FFF #FFF '>
 <div class='gradient'> 
 <div class='titleLine' >
<span class='searchBar' macro='search'></span>
 <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
 <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
 </div>
<div id='topMenu' refresh='content' tiddler='MainMenu'></div>
 </div>
</div>
<div id='bodywrapper'>
<div id='sidebar'>
 <div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
 <div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
 <div id='messageArea'></div>
 <div id='tiddlerDisplay'></div>
</div>
<div id='displayFooter'></div>
</div>
Esta receita segue o meu gosto pessoal e refere-se a um servidor com Red Hat Enterprise Linux 5, não registado, sem actualizações, com o SELinux desactivado e sem nenhum //role// escolhido durante o processo de instalação.

Para começar, registar o sistema na //Red Hat Network// para podermos utilizar o {{{yum}}}:
{{{
$ rhn_register
}}}

Evitar ter de usar o {{{vi}}} para editar os ficheiros de configuração que se seguem...
{{{
$ yum install joe
}}}

Editar o ficheiro {{{/etc/fstab}}} e...
# Para os volumes LVM, substituir as //labels// pelo nome do volume;
# Acrescentar o parâmetro {{{acl}}} a todos os //filesystems// {{{ext3}}} locais, excepto a {{{/boot}}};
# Adicionar uma entrada para o leitor de CD:
{{{
/dev/cdrom /media/cdrom auto defaults,ro,noauto 0 0
}}}

Não queremos mostrar demasiada informação sobre a máquina aos utilizadores que se ligam remotamente, portanto criamos um novo ficheiro {{{/etc/issue.net}}}. Por exemplo:
{{{
/*
 |
 | Welcome to <maquina>
 |
 | Authorized access only. All connections are logged.
 | Apenas acesso autorizado. Todas as ligacoes sao registadas.
 |
 */
}}}

Adicionar o utilizador criado durante a instalação ao grupo {{{users}}} com o comando:
{{{
$ usermod -G users <utilizador>
}}}

Editar o ficheiro {{{/etc/ssh/sshd_config}}} e definir...
{{{
PermitRootLogin no     # não queremos acessos remotos do root
AllowGroups users      # não queremos aceitar qualquer utilizador
Banner /etc/issue.net  # queremos mostrar uma mensagem antes do login
}}}

Correr o comando {{{visudo}}} para alterar a configuração do {{{sudo}}} e adicionar...
{{{
Defaults targetpw         # pedir a password do root em vez da password do utilizador
utilizador ALL=(ALL) ALL  # dar privilégios ao utilizador criado durante a instalação
}}}

Infelizmente, algum software proprietário ainda tem problemas com internacionalização. Por isso, edita-se o ficheiro {{{/etc/sysconfig/i18n}}} e substitui-se {{{en_US.UTF-8}}} por...
{{{
LANG="en_US"
}}}

Instalar o pacote {{{sendmail-cf}}} para podermos alterar a configuração do {{{sendmail}}}:
{{{
$ yum install sendmail-cf
}}}
Editar o ficheiro {{{/etc/mail/sendmail.mc}}}, configurar o {{{SMART_HOST}}} e correr {{{make}}} para gerar a configuração nova.

Editar o ficheiro {{{/etc/aliases}}} para enviar o email do {{{root}}} também para o endereço do administrador:
{{{
root: root,admin@example.com
}}}

Desactivar alguns serviços que não interessa ter a correr num servidor:
{{{
$ chkconfig avahi-daemon off
$ chkconfig rhnsd off
$ chkconfig yum-updatesd off
}}}
Activar o //Name Service Caching Daemon//:
{{{
$ chkconfig nscd on
}}}

Configurar a monitorização dos discos locais editando o {{{/etc/smartd.conf}}}.

Se a máquina suportar IPMI, instalar o software necessário e activar o serviço:
{{{
$ yum install OpenIPMI-tools
$ chkconfig ipmi on
}}}
Adicionalmente, editar o ficheiro {{{/etc/sysconfig/ipmi}}} para configurar o //watchdog// IPMI.

Remover alguns pacotes que não interessam:
{{{
$ rpm -e logwatch isdn4k-utils hplip irda-utils pcsc-lite \
         vnc-server ifd-egate ccid coolkey esc autofs bluez-gnome \
         bluez-libs bluez-utils ypbind yp-tools java-1.4.2-gcj-compat \
         libgcj gjdoc antlr
}}}
E instalar alguns pacotes interessantes:
{{{
$ yum install sysstat procinfo iptraf strace ltrace screen lynx lsscsi gcc gcc-c++
}}}

Criar um //script// executável {{{/etc/profile.d/profile.local.sh}}} com definições específicas desta máquina (//aliases//, acrescentos à {{{PATH}}}, ...).

Criar uma directoria {{{/root/bin}}} para colocar eventuais //scripts// de administração.

Configurar a //firewall// com a ferramenta {{{system-config-securitylevel}}}.

Finalmente, fazer as actualizações do sistema e limpar o lixo:
{{{
$ yum update
$ yum clean all
$ rpm --rebuilddb
}}}

Reiniciar a máquina para tornar as configurações efectivas.
O VMware introduz alguns problemas de sincronização do relógio de sistema em sistemas operativos que mantêm o seu próprio relógio, ao invés de recorrerem regularmente ao relógio de hardware (BIOS/RTC). Em alguns casos estes problemas não se notam, mas são bastante agravados pelo ritmo elevado do //timer// definido pelo Linux 2.6.x (250Hz ou 1000Hz, contra os 100Hz da versão 2.4.x) e os atrasos (ou avanços) do relógio acumulam-se rapidamente (já vi atrasos de 30 segundos por cada minuto real, numa máquina em carga).

Este problema é tão grave que o esquema de controlo do relógio fornecido pelas //vmware-tools// é incapaz de dar conta do recado.

!!Debian 3.1 (sarge) -- Linux 2.6 com timer de 1000Hz
O primeiro passo é recompilar o kernel com o //timer// modificado para 100Hz (quanto mais elevado for, maior carga sobre o VMware, maior o desfasamento do relógio): [[Compilar um kernel personalizado em Debian]]

O patch seguinte faz as modificações necessárias para o kernel fornecido com o Debian 3.1 (sarge):
{{{
diff -ruN kernel-source-2.6.8-orig/include/asm-i386/param.h kernel-source-2.6.8/include/asm-i386/param.h
--- kernel-source-2.6.8-orig/include/asm-i386/param.h   2004-08-14 06:36:17.000000000 +0100
+++ kernel-source-2.6.8/include/asm-i386/param.h        2005-07-03 02:57:04.000000000 +0100
@@ -2,7 +2,7 @@
 #define _ASMi386_PARAM_H

 #ifdef __KERNEL__
-# define HZ            1000            /* Internal kernel timer frequency */
+# define HZ            100             /* Internal kernel timer frequency */
 # define USER_HZ       100             /* .. some user interfaces are in "ticks" */
 # define CLOCKS_PER_SEC                (USER_HZ)       /* like times() */
 #endif
}}}
Agora é necessário descobrir qual dos mecanismos se aguenta melhor, se o {{{ntpd}}} ou as //vmware-tools//. A VMware desaconselha o {{{ntpd}}}, mas eu já conclui que por vezes é ''bastante'' mais eficaz.

Depois é necessário passar os seguintes parâmetros ao kernel:
{{{
noapic nolapic nosmp clock=pmtmr
}}}
No caso de um //guest// [[Debian|http://www.debian.org]] isto pode ser conseguido acrescentando-os à linha...
{{{
# kopt=root=/dev/sda1 ro
}}}
...no ficheiro {{{/boot/grub/menu.lst}}}. Esta linha é um comentário, mas é também uma directiva para o {{{update-grub}}}, que se encarregará de fazer as restantes modificações necessárias. Este deverá ser executado antes da máquina ser reiniciada:
{{{
$ /sbin/update-grub
}}}
Se se concluir que (especialmente num //guest// ou //host// com alguma carga) os passos acima não são suficientes, sempre se pode recorrer ao {{{ntpdate}}} para sincronizar o relógio regularmente (de 3 em 3 horas deverá ser suficiente), adicionando à directoria {{{/etc/cron.d}}} um ficheiro {{{ntpdate-hostname}}} com o seguinte conteúdo:
{{{
0 */3 * * *     root    /usr/sbin/ntpdate -s -u pool.ntp.org > /dev/null
}}}

O VMware definitivamente não é uma boa opção para serviços que necessitem de boa precisão temporal.

!!Debian 4.0 (etch) -- Linux 2.6 com timer de 250Hz
Com o Debian 4.0 (etch) e uma versão recente do VMware (Workstation 5.5.x ou Server 1.0.x) as {{{vmware-tools}}} já conseguem dar conta do atraso do relógio, e passam a ser a forma preferencial de o manter certo. Neste caso, basta passar os seguintes parâmetros ao kernel:
{{{
noapic nolapic nosmp clocksource=acpi_pm
}}}
Neste caso também deixa de ser necessário recompilar o kernel, já que o //timer// passa a estar definido como 250Hz por omissão.
Em Linux, qualquer //block device// pode ser usado como componente de um //array// RAID por software, desde discos físicos a volumes lógicos [[LVM|Storage em Linux com LVM]]. No entanto, o mais comum é usar partições de discos, e é isso que vamos usar nos exemplos abaixo.

Antes de seguir em frente, é necessário instalar a ferramenta {{{mdadm}}}. Em Debian, basta fazer...
{{{
$ aptitude install mdadm
}}}
Como extra, este pacote configura imediatamente a monitorização de todos os //arrays// RAID activos, enviando notificações para o email do {{{root}}} sempre que ocorra algo  importante (avaria num disco, por exemplo).

!!Criação do //array//
Para colocar dois discos em RAID-1 (//mirror//), começamos por criar no primeiro uma partição de tipo //Linux raid autodetect// usando o {{{cfdisk}}} (ou outra ferramenta de particionamento). Esta partição deverá ser ligeiramente inferior à capacidade total do disco para permitir a sua substituição por um disco de outro fabricante em caso de avaria. (Para uma dada capacidade anunciada, discos de fabricantes diferentes podem ter capacidades ligeiramente diferentes.)

No segundo disco deverá ser criada uma partição equivalente. Se os discos são ''iguais'', isto pode ser feito através da simples cópia da tabela de partições do primeiro disco:
{{{
$ sfdisk -d /dev/sdb | sfdisk /dev/sdc
}}}
Se os discos são ''diferentes'', a partição do segundo disco deverá ser criada manualmente. Se, por alguma razão, não se conseguir criar uma partição com exactamente a mesma capacidade da partição do primeiro disco, também não há problema, pois o //array// ficará com o tamanho da partição mais pequena. Neste aspecto o RAID por software em Linux é bastante flexível.

Criamos então um //array// de nome {{{md0}}} usando o seguinte comando:
{{{
$ mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1
}}}
Nesta altura inicia-se o processo de sincronização, cujo progresso pode ser acompanhado com {{{cat /proc/mdstat}}}. O //array// pode começar a ser utilizado imediamente, mesmo enquanto este processo decorre.

!!Criação do //array// (modo degradado)
É possível criar um //array// com apenas um disco, utilizando {{{missing}}} no lugar do outro disco:
{{{
$ mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 missing
}}}
Isto pode ser útil quando, por exemplo, queremos começar a utilizar um //array// imediatamente e ainda não temos o segundo disco disponível. Este pode ser adicionado mais tarde com o comando...
{{{
$ mdadm --add /dev/md0 /dev/sdc1
}}}

!!Debian
Em Debian, por omissão, todos os módulos associados ao RAID por software são carregados durante o arranque do sistema. Para que apenas sejam carregados os módulos necessários para o RAID-1, devemos actualizar o ficheiro de configuração {{{/etc/mdadm/mdadm.conf}}} e a imagem //initrd// do sistema. Isto faz-se executando os comandos:
{{{
$ /usr/share/mdadm/mkconf force-generate
$ update-initramfs -u -k all
}}}
Note-se que isto é recomendado, mas não é obrigatório. O próprio //kernel// detecta e inicializa automaticamente os RAIDs baseados em partições de tipo //Linux raid autodetect//, e ter módulos carregados relativos a níveis RAID não utilizados também não faz mal, para além de consumir um pouco de memória.

!!Mais informação
Para listar os arrays RAID disponíveis na máquina, pode usar-se o comando:
{{{
$ mdadm --detail --scan
}}}
Para obter mais detalhes sobre um //array//, para além do que se pode ver no ficheiro {{{/proc/mdstat}}}, faz-se...
{{{
$ mdadm --detail /dev/md0
}}}

!!Remover e adicionar discos
Para remover um disco (partição) de um //array// usam-se os comandos seguintes:
{{{
$ mdadm --fail /dev/md0 /dev/sdc1
$ mdadm --remove /dev/md0 /dev/sdc1
}}}
Quando um disco avaria, o sistema marca-o como //failed//, pelo que apenas é necessário executar o segundo comando ({{{--remove}}}) antes de o remover fisicamente da máquina.

Para adicionar um disco (partição) novo em substituição de um disco avariado, ou para voltar a adicionar um disco (partição) anteriormente removido:
{{{
$ mdadm --add /dev/md0 /dev/sdc1
}}}
Se adicionarmos um terceiro disco a um //array// criado com {{{--raid-devices=2}}}, este torna-se um //spare//. Em caso de avaria de um dos discos activos, o //spare// é colocado no seu lugar automaticamente.

!!Activação manual
Em alguns casos pode ser necessário activar um //array// manualmente. Imaginemos que, por alguma razão, um dos discos de um array RAID-1 é colocado numa caixa de discos externos e ligada a outra máquina. Para activar um novo //array// na máquina de destino, utilizando apenas este disco, é necessário fazer:
{{{
$ mdadm --assemble --run /dev/md1 /dev/sdd1
}}}
Onde {{{md1}}} é um nome livre na máquina de destino e {{{sdd1}}} é o nome atribuído ao disco externo.

A opção {{{--run}}} é necessária para activar o //array// em modo degradado (sem estarem presentes todos os seus componentes). Se todos os componentes estiverem disponíveis, podemos usar o comando:
{{{
$ mdadm --assemble /dev/md1 /dev/sdd1 /dev/sde1
}}}

!!Destruição de um //array//
Não existe propriamente um comando para destruir um //array//. A única forma de o fazer consiste em desactivá-lo e, de seguida, escrever zeros sobre cada um dos componentes. Assim:
{{{
$ mdadm --stop /dev/md0
$ mdadm --zero-superblock /dev/sdb1
$ mdadm --zero-superblock /dev/sdc1
}}}
Assim, mesmo que as partições {{{sdb1}}} e {{{sdc1}}} tenham o tipo //Linux raid autodetect//, não serão reconhecidas como tal nem activadas automaticamente durante o arranque.
Quando se usa o {{{apt-get}}} em vez do {{{aptitude}}} para gerir pacotes, a base de dados deste último pode perder a sincronização com a base de dados de pacotes realmente instalados no sistema ({{{dpkg -l}}}), dando origem a comportamentos bizarros, como a sugestão de pacotes obsoletos para instalação. Esta situação é simples de corrigir, basta fazer:
{{{
$ rm /var/lib/aptitude/pkgstates
$ aptitude update
$ aptitude install pacote_inexistente
}}}

!!Moral da história...
Usar sempre o {{{aptitude}}}.
Em determinadas situações o browser pode determinar um //charset// errado para uma página, mesmo quando a própria página contém a definição correcta. Isto pode ser provocado pelo Apache, ao enviar um //header// {{{Content-type}}} contendo um //charset// diferente do declarado no HTML.

Neste caso basta criar um ficheiro {{{.htaccess}}} na área web com a seguinte linha:
{{{
AddDefaultCharset Off
}}}
Instalar o samba:
{{{
$ aptitude install samba samba-common
}}}
Substituir o ficheiro {{{/etc/samba/smb.conf}}} existente por outro com o seguinte conteúdo:
{{{
[global]
   workgroup = WORKGROUP
   server string = Server Description
   security = user
   obey pam restrictions = yes
   passdb backend = tdbsam
   pam password change = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Enter\snew\sUNIX\spassword:* %n\n *Retype\snew\sUNIX\spassword:* %n\n .
   unix password sync = yes
   max log size = 1000
   dns proxy = no
   panic action = /usr/share/samba/panic-action %d
   invalid users = root
   load printers = no

[homes]
   comment = Home Directories
   valid users = %S
   browseable = no
   read only = no
   create mask = 0664
}}}
Depois é só tentar aceder a um //share// {{{\\servidor\username}}}. Se o servidor se recusar a aceitar as passwords dos utilizadores, é necessário adicioná-las manualmente ao samba recorrendo ao comando:
{{{
$ smbpasswd username
}}}
Se o problema não for das passwords, mas dos próprios utilizadores não serem reconhecidos pelo samba, então o comando para lhe adicionar um utilizador novo será:
{{{
$ smbpasswd -a username
}}}
Em primeiro lugar, adicionar ao {{{/etc/services}}}, se não existir, a linha:
{{{
sane-port            6566/tcp        saned           # SANE network scanner daemon
}}}
Depois criar o ficheiro {{{/etc/xinetd.d/sane-port}}} com o seguinte conteúdo:
{{{
service sane-port
{
    disable = no
    socket_type = stream
    server = /usr/sbin/saned
    protocol = tcp
    user = root
    group = root
    wait = no
    bind = 192.168.0.1
}
}}}
Reiniciar o {{{xinetd}}} e adicionar ao {{{/etc/sane.d/saned.conf}}} os enderecos dos clientes, p. ex.:
{{{
192.168.0.0/24
}}}
Finalmente, adicionar ao {{{/etc/sane.d/net.conf}}} dos clientes o servidor, p. ex.:
{{{
scanserver.example.com
}}}
Para montar uma espécie de //terminal server// baseado em VNC e X, seguir os seguintes passos:

Se está a usar o {{{inetd}}} (o //default// em [[Debian|http://www.debian.org]]), acrescente a seguinte linha ao {{{/etc/inetd.conf}}}:
{{{
5900 stream tcp nowait nobody /usr/bin/Xvnc Xvnc -inetd -query localhost -once securitytypes=none
}}}
Se está a usar o {{{xinetd}}}, criar um novo ficheiro {{{/etc/xinetd.d/vncserver}}} com o seguinte conteúdo:
{{{
service vncserver
{
    socket_type = stream
    type = UNLISTED
    port = 5900
    wait = no
    user = nobody
    server = /usr/bin/Xvnc
    server_args = -inetd -query localhost -once securitytypes=none
    log_on_success += HOST DURATION
    log_on_failure += HOST
    disable = no
}
}}}

!!Notas
* Esta configuração aplica-se ao [[TightVNC|http://tightvnc.sourceforge.net]]. O [[RealVNC|http://www.realvnc.com]] aceita parâmetros ligeiramente diferentes, mas é apenas uma questão de consultar a //manpage//.
* Estas sessões X são criadas no momento do login, e morrem no momento em que o cliente se desliga. Não têm qualquer tipo de persistência semelhante ao [[RDP]].
<<closeAll>><<permaview>><<newTiddler>><<newJournal 'DD MMM YYYY'>><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
administração de sistemas
Carlos Rodrigues
Esta receita refere-se à versão //Etch// do Debian.

Para começar, instalar algum software importante que não requer configurações extra:
{{{
$ aptitude install acpid anacron slocate sysstat nscd sysutils schedutils \
                   pciutils psmisc iproute ethtool ifstat iptraf smartmontools  \
                   hdparm lvm2 dmsetup bzip2 zip unzip apt-file deborphan debsums \
                   acl sudo strace ltrace screen ksh tree joe pinfo lynx
}}}
Depois disto pode ser útil actualizar imediatamente a base de dados do {{{slocate}}} e do {{{apt-file}}}, fazendo:
{{{
$ /etc/cron.daily/slocate
$ apt-file update
}}}
E também definir um editor não horrível como //default//, em lugar do {{{vi}}}:
{{{
$ update-alternatives --set editor /usr/bin/joe
}}}
Instalar um novo kernel especialmente optimizado para o processador da máquina (se o instalador não o tiver feito automaticamente por alguma razão), por exemplo:
{{{
$ aptitude install linux-image-2.6.18-3-k7
}}}
Instalar os pacotes necessários à compilação de módulos extra para o kernel, por exemplo:
{{{
$ aptitude install linux-headers-2.6.18-3-k7 linux-kbuild-2.6.18
}}}
O instalador do //etch// (i386) instala uma versão da biblioteca do C para amd64. Suponho que isto seja necessário para o caso de querermos corrrer um kernel de 64bit com uma //userland// (maioritariamente) de 32bit, mas este é um caso raro, portanto...
{{{
$ aptitude purge libc6-amd64
}}}
Instalar o pacote //resolvconf// para uma melhor gestão do {{{/etc/resolv.conf}}}:
{{{
$ aptitude install resolvconf
}}}
Instalar um //daemon// de NTP:
{{{
$ aptitude install ntp ntpdate
}}}
Insta