Este guia detalha o processo de instalação e configuração do Wiki.js em um ambiente Docker, com foco na criação de uma homepage moderna e funcional. O passo a passo abrange desde a configuração inicial do Docker, passando pela orquestração com Docker Compose, até a personalização da interface com CSS e Markdown avançado.
Antes de implantar o Wiki.js, é crucial configurar um ambiente Docker robusto e seguro. Esta seção aborda a instalação do Docker, a configuração para suporte a redes dual-stack (IPv4 e IPv6) e a criação da infraestrutura de rede necessária.
Os comandos a seguir atualizam o sistema e instalam o Docker Engine. A adição do repositório oficial do Docker garante que você receba as atualizações mais recentes.
# Atualiza a lista de pacotes e instala dependências necessárias
'sudo apt update && sudo apt upgrade -y'
'sudo apt install -y apt-transport-https ca-certificates curl gnupg lsb-release'
# Adiciona a chave GPG oficial do Docker
'curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg'
# Adiciona o repositório do Docker às fontes do APT
'echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null'
# Instala o Docker Engine, CLI, e plugins essenciais
'sudo apt-get update'
'sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin'
# Adiciona o usuário atual ao grupo 'docker' para executar comandos sem 'sudo'
'sudo usermod -aG docker ${USER}'
Nota: Após adicionar o usuário ao grupo
docker, é necessário fazer logout e login novamente para que as alterações de permissão entrem em vigor.
Para que os contêineres possam se comunicar utilizando tanto IPv4 quanto IPv6, o daemon do Docker precisa ser configurado adequadamente. O arquivo /etc/docker/daemon.json centraliza essas configurações.
// /etc/docker/daemon.json
{
"ipv6": true, // Habilita o suporte a IPv6
"ip6tables": true, // Habilita a integração com ip6tables para regras de firewall
"userland-proxy": false, // Desabilitado para melhor performance de rede
"log-driver": "json-file", // Define o driver de log
"log-opts": {
"max-size": "10m", // Limita o tamanho de cada arquivo de log
"max-file": "3" // Limita o número de arquivos de log rotacionados
},
"default-address-pools": [
{"base": "192.168.0.0/16", "size": 24}, // Define um pool de endereços IPv4 para as redes Docker
{"base": "fd00::/56", "size": 64} // Define um pool de endereços IPv6 para as redes Docker
]
}
Após criar ou modificar este arquivo, reinicie o sistema para aplicar as configurações.
'sudo reboot'
Após a reinicialização, verifique se o Docker está funcionando corretamente.
'docker info'
'docker version'
Criaremos uma rede dedicada para o proxy reverso, que será responsável por direcionar o tráfego externo para os contêineres apropriados. Isolar o proxy em sua própria rede melhora a segurança e a organização.
'docker network create \'
' --driver=bridge \'
' --subnet=10.112.0.0/24 \'
' --gateway=10.112.0.1 \'
' --ip-range=10.112.0.0/25 \' # Garante que o IP do proxy fique fora do range de IPs dinâmicos
' --ipv6 \'
' --subnet=fd00:112:96::/64 \'
' --gateway=fd00:112:96::1 \'
' proxy-net'
Uma estrutura de diretórios bem organizada é fundamental para a manutenção do ambiente. Criaremos diretórios para armazenar os arquivos de configuração do Docker Compose e do Nginx.
'sudo mkdir -p /opt/stacks/proxy/nginx/templates /opt/stacks/proxy/nginx/conf.d /opt/stacks/proxy/certbot/conf /opt/stacks/proxy/certbot/www'
'sudo mkdir -p /opt/stacks/wikijs'
O Docker Compose orquestra a implantação de aplicações multi-contêiner. Para o Wiki.js, usaremos dois serviços: db para o banco de dados PostgreSQL e wikijs para a aplicação em si.
docker-compose.yml para o Wiki.jsEste arquivo define os serviços, redes e volumes necessários para executar o Wiki.js. Salve-o como /opt/stacks/wikijs/docker-compose.yml.
# /opt/stacks/wikijs/docker-compose.yml
services:
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: wikijs
POSTGRES_USER: wikijs
POSTGRES_PASSWORD: ${DB_PASS} # A senha será lida de um arquivo .env
healthcheck:
test: ["CMD-SHELL", "pg_isready -U wikijs -d wikijs"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- wikijs-net
volumes:
- db-data:/var/lib/postgresql/data # Persiste os dados do banco de dados
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
mem_limit: 2g
cpus: '1.0'
wikijs:
image: ghcr.io/requarks/wiki:2
depends_on:
db:
condition: service_healthy # Garante que o wiki só inicie após o banco de dados estar pronto
environment:
DB_TYPE: postgres
DB_HOST: db
DB_PORT: 5432
DB_USER: wikijs
DB_PASSWORD: ${DB_PASS}
DB_NAME: wikijs
restart: unless-stopped
networks:
- wikijs-net # Rede interna para comunicação com o banco
- proxy-net # Rede externa para comunicação com o proxy
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
mem_limit: 1g
cpus: '1.0'
networks:
wikijs-net:
driver: bridge
proxy-net:
external: true # Declara que esta rede foi criada externamente
volumes:
db-data:
Crie um arquivo .env no mesmo diretório (/opt/stacks/wikijs/) para armazenar a senha do banco de dados de forma segura. Em seguida, inicie os contêineres.
# Crie o arquivo .env com a senha do banco de dados
'echo "DB_PASS=sua-senha-super-segura" > /opt/stacks/wikijs/.env'
# Navegue até o diretório e inicie os serviços em background
'cd /opt/stacks/wikijs'
'docker-compose up -d'
# Monitore os logs para verificar se tudo iniciou corretamente
'docker-compose logs -f'
O proxy reverso é o portão de entrada para sua aplicação. Ele recebe as requisições da internet e as encaminha para o contêiner do Wiki.js. Usaremos o Nginx para essa função e o Certbot para automatizar a obtenção e renovação de certificados SSL/TLS, garantindo uma comunicação segura via HTTPS.
docker-compose.yml para o ProxyEste arquivo, localizado em /opt/stacks/proxy/docker-compose.yml, define os serviços do Nginx e do Certbot.
# /opt/stacks/proxy/docker-compose.yml
services:
nginx:
image: nginx:1-alpine
container_name: proxy_nginx
restart: unless-stopped
ports:
# Expõe as portas 80 (HTTP) e 443 (HTTPS) no host
- "80:80"
- "443:443"
volumes:
- ./nginx/templates:/etc/nginx/templates:ro
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/templates/dhparam.pem:/etc/nginx/templates/dhparam.pem:ro
- certbot_conf:/etc/letsencrypt:ro
- certbot_www:/var/www/certbot
environment:
- PRIMARY_DOMAIN=${PRIMARY_DOMAIN}
- TZ=${TZ}
networks:
proxy-net:
ipv4_address: 10.112.0.200 # IP estático para o proxy na rede compartilhada
ipv6_address: fd00:112:96::200
command: /bin/sh -c "envsubst '\$${PRIMARY_DOMAIN}' < /etc/nginx/templates/nginx.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
certbot:
image: certbot/certbot:latest
container_name: proxy_certbot
restart: unless-stopped
depends_on:
- nginx
volumes:
- certbot_conf:/etc/letsencrypt
- certbot_www:/var/www/certbot
networks:
- proxy-net
# O entrypoint para renovação automática deve ser descomentado após a criação inicial dos certificados
# entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
volumes:
certbot_conf:
certbot_www:
networks:
proxy-net:
external: true
Crie o arquivo /opt/stacks/proxy/.env para configurar as variáveis usadas pelo Nginx e Certbot.
# /opt/stacks/proxy/.env
# Email para notificações do Let's Encrypt (importante para alertas de expiração)
CERTBOT_EMAIL=seu-email@dominio.com
# Domínio principal para o qual o certificado será emitido
PRIMARY_DOMAIN=wiki.seudominio.com
# Fuso Horário para logs e agendamentos
TZ=America/Sao_Paulo
Estes arquivos modulares tornam a configuração do Nginx mais limpa e reutilizável.
Template Principal (nginx.template):
Este arquivo é o modelo para a configuração principal do Nginx. A variável ${PRIMARY_DOMAIN} será substituída pelo valor definido no arquivo .env quando o contêiner iniciar.
# /opt/stacks/proxy/nginx/templates/nginx.template
# Bloco HTTP: Redireciona todo o tráfego para HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
# Rota para o desafio de validação do Let's Encrypt
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Redirecionamento permanente para a versão HTTPS do site
location / {
return 301 https://$host$request_uri;
}
}
# Bloco HTTPS: Configurações para o Wiki.js
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name wiki.${PRIMARY_DOMAIN};
# Caminhos para os certificados SSL gerados pelo Certbot
ssl_certificate /etc/letsencrypt/live/${PRIMARY_DOMAIN}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/${PRIMARY_DOMAIN}/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/${PRIMARY_DOMAIN}/chain.pem;
# Inclui parâmetros de segurança SSL
include /etc/nginx/templates/ssl_params.conf;
# Cabeçalhos de segurança para proteção contra ataques comuns
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin";
proxy_hide_header X-Powered-By;
location / {
# Repassa a requisição para o contêiner do Wiki.js
proxy_pass http://wikijs:3000;
include /etc/nginx/templates/proxy_params.conf;
client_max_body_size 50M; # Permite uploads de arquivos maiores
}
}
Parâmetros de Proxy (proxy_params.conf):
# /opt/stacks/proxy/nginx/templates/proxy_params.conf
# Encaminha cabeçalhos importantes para a aplicação de backend
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
Parâmetros de SSL (ssl_params.conf):
# /opt/stacks/proxy/nginx/templates/ssl_params.conf
# Arquivo de parâmetros Diffie-Hellman para maior segurança
ssl_dhparam /etc/nginx/templates/dhparam.pem;
# Protocolos e cifras SSL/TLS modernos e seguros
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:EECDH+CHACHA20:EECDH+AESGCM;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519:secp384r1;
# Configurações de cache de sessão para performance
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
# Desabilitado por padrão, pode ser ativado se necessário
ssl_stapling off;
# Resolvers para OCSP Stapling
resolver 1.1.1.1 8.8.8.8 [2606:4700:4700::1111] [2001:4860:4860::8888] valid=3600s;
resolver_timeout 5s;
O arquivo de parâmetros Diffie-Hellman (DH) fortalece a segurança da troca de chaves SSL/TLS. Gere-o com o seguinte comando:
'openssl dhparam -out /opt/stacks/proxy/nginx/templates/dhparam.pem 2048'
Com o Nginx configurado, mas ainda sem os certificados, vamos usar o Certbot para gerá-los.
Inicie o contêiner do Nginx:
'cd /opt/stacks/proxy'
'docker-compose up -d nginx'
Execute o Certbot em modo de teste (--staging):
Isso permite verificar se a configuração está correta sem atingir os limites de requisição da Let's Encrypt.
'docker-compose run --rm certbot certonly \'
' --webroot --webroot-path /var/www/certbot \'
' --email ${CERTBOT_EMAIL} --agree-tos --no-eff-email \'
' --staging \'
' -d ${PRIMARY_DOMAIN}'
Gere os certificados de produção:
Se o teste foi bem-sucedido, remova o parâmetro --staging para obter os certificados reais.
'docker-compose run --rm certbot certonly \'
' --webroot --webroot-path /var/www/certbot \'
' --email ${CERTBOT_EMAIL} --agree-tos --no-eff-email \'
' -d ${PRIMARY_DOMAIN}'
Reinicie o Stack Completo:
Agora, com os certificados no lugar, reinicie todo o stack do proxy. O Nginx irá carregar os certificados e começar a servir tráfego em HTTPS.
'docker-compose up -d --force-recreate'
Habilite a Renovação Automática:
Descomente a linha entrypoint no serviço certbot do arquivo /opt/stacks/proxy/docker-compose.yml e reinicie o serviço para que os certificados sejam renovados automaticamente.
'docker-compose up -d --force-recreate certbot'
Com a infraestrutura implantada, o próximo passo é personalizar a aparência e o conteúdo da sua homepage no Wiki.js. Esta seção mostra como adicionar ícones, criar um rodapé customizado e estruturar o conteúdo com abas e tabelas.
Nota: As configurações a seguir são aplicadas na interface de administração do Wiki.js, geralmente acessível em
https://wiki.seudominio.com.
Para utilizar uma vasta gama de ícones em sua wiki, vamos carregar a biblioteca Font Awesome. Isso é feito injetando uma linha de HTML no cabeçalho de todas as páginas.
Administration -> Theme.Code Injection.Head HTML Injection, insira o seguinte código:<!-- Carrega a biblioteca de ícones Font Awesome a partir de um CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
Explicação: Este link aponta para uma Content Delivery Network (CDN), que hospeda a folha de estilos (CSS) do Font Awesome. Usar um CDN é eficiente, pois os navegadores podem já ter o arquivo em cache de outras visitas a sites que também o utilizam.
O CSS a seguir cria um layout de rodapé em formato de grid, que é responsivo e se adapta a diferentes tamanhos de tela.
Administration -> Theme.Code Injection.CSS Override, insira o seguinte código:/* ============================================
Rodapé com cards (estilo consistente com a wiki)
============================================ */
.footer-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 1.5rem;
margin-top: 2rem;
}
.footer-card {
background-color: #f0f4f8; /* Mesmo fundo do details */
border-radius: 8px;
padding: 1.25rem;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
transition: box-shadow 0.2s ease-in-out;
}
.footer-card:hover {
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.footer-card h4 {
margin-top: 0;
margin-bottom: 1rem;
font-size: 1.1rem;
color: #1a237e; /* Azul indigo dos títulos */
border-bottom: 2px solid rgba(25,118,210,0.3); /* Azul Wiki.js com transparência */
padding-bottom: 0.5rem;
}
.footer-card ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer-card li {
margin: 0.75rem 0;
}
.footer-card a {
text-decoration: none;
color: #1976d2; /* Azul padrão Wiki.js */
display: flex;
align-items: center;
gap: 0.75rem;
transition: color 0.2s ease-in-out, transform 0.2s ease-in-out;
}
.footer-card a:hover {
color: #0d47a1; /* Azul mais escuro no hover */
text-decoration: underline;
transform: translateX(4px); /* Leve deslocamento para a direita */
}
/* Ícones mantêm a cor padrão, mas podem ganhar um efeito sutil */
.footer-card a i {
font-size: 1.2rem;
transition: transform 0.2s ease-in-out;
}
.footer-card a:hover i {
transform: scale(1.1); /* Aumenta levemente o ícone */
}
/* Responsividade para telas pequenas */
@media (max-width: 768px) {
.footer-grid {
grid-template-columns: 1fr;
}
}
/* =============================================
Estilização avançada do container <details>
============================================= */
details {
background-color: #f0f4f8; /* Fundo azul acinzentado claro */
border-left: 4px solid #1976d2; /* Azul padrão Wiki.js */
border-radius: 8px;
padding: 0.75rem 1.25rem;
margin: 1.5rem 0;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
transition: all 0.2s ease-in-out;
}
/* Efeito ao passar o mouse – borda mais grossa e fundo ligeiramente mais escuro */
details:hover {
background-color: #e3eaf2;
border-left-width: 8px; /* Aumenta a borda para feedback tátil */
transition: border-left-width 0.2s ease-in-out; /* Transição suave apenas na borda */
}
/* Quando aberto, ganha uma sombra interna para destacar o estado expandido */
details[open] {
box-shadow: inset 0 0 0 1px rgba(25,118,210,0.2), 0 1px 3px rgba(0,0,0,0.1);
}
/* =============================================
Estilização do sumário (cabeçalho clicável)
============================================= */
details summary {
font-weight: 600;
color: #1a237e; /* Azul indigo escuro */
cursor: pointer;
outline: none;
display: flex;
align-items: flex-start; /* Alinhamento superior para textos longos */
gap: 10px;
list-style: none; /* Remove marcador padrão (Firefox) */
}
/* Remove o marcador padrão no Chrome/Safari/Edge */
details summary::-webkit-details-marker {
display: none;
}
/* Ícone customizado (triângulo para a direita) */
details summary::before {
content: '▶';
font-size: 0.7rem;
transition: transform 0.2s, color 0.2s;
color: #1976d2;
display: inline-block;
line-height: 1.5; /* Ajuda no alinhamento vertical */
}
/* Cor do ícone ao passar o mouse sobre o sumário */
details summary:hover::before {
color: #0d47a1; /* Azul mais escuro */
}
/* Quando aberto, o triângulo gira 90° para baixo */
details[open] summary::before {
transform: rotate(90deg);
}
/* Linha divisória quando aberto, separando o título do conteúdo */
details[open] summary {
border-bottom: 1px solid rgba(0,0,0,0.1);
margin-bottom: 1rem;
padding-bottom: 0.5rem;
}
Finalmente, crie ou edite sua página inicial com o seguinte conteúdo Markdown. Ele combina metadados, badges informativos, um sistema de abas para organizar o conhecimento, uma tabela de acesso rápido e o rodapé personalizado.
---
title: Terminal de Conhecimento TI
description: Hub central para estudos de infraestrutura, automação e desenvolvimento.
tags:
- home
- dashboard
- index
---
# Base de Conhecimento: Infra & Ops
<!-- Badges do Shields.io para status visual -->
 
> "O conhecimento é o único ativo que cresce quando é compartilhado."
Bem-vindo ao meu repositório pessoal de documentação técnica. Este espaço serve como um hub central para meus estudos, anotações e guias práticos sobre infraestrutura, automação e desenvolvimento.
---
## Ecossistema Tecnológico {.tabset}
*Selecione uma trilha para explorar os documentos relacionados.*
### Core & Sistemas
* **[Linux Essentials](/linux)** - Kernel, Shell Script, Administração.
* **[File System](/filesystem)** - Estruturas, Particionamento e LVM.
* **[Network](/network)** - Protocolos, Firewall e Troubleshooting.
### Containers & Orquestração
* **[Docker](/docker)** - Imagens, Runtime e Compose.
* **[Kubernetes](/kubernetes)** - Clusters, Pods e Helm Charts.
### Automação & IaC
* **[Ansible](/ansible)** - Playbooks, Roles e Automação de Configuração.
* **[Terraform](/terraform)** - Provisionamento de Infraestrutura como Código.
---
## Acesso Rápido (Cheat Sheets)
| Tópico | Atalho de Comando | Referência Conceitual |
| :--------- | :---------------------------------------------------- | :---------------------------------------------------------- |
| **Linux** | [Gerador de Senhas (Bash)](/linux/bash/gerar-senha) | [VIM Essentials](/linux/vim) |
| **Docker** | [Comandos Frequentes](/docker/guia-comandos) | [Dockerfile Best Practices](/docker/best-practices) |
| **K8s** | [Troubleshooting Pods](/kubernetes/troubleshooting-pods) | [kubectl Master Class](/kubernetes/kubectl) |
---
## Conecte-se & Referências
<!-- O HTML abaixo cria a estrutura do rodapé usando as classes CSS definidas anteriormente -->
<div class="footer-grid">
<!-- Card: Conecte-se -->
<div class="footer-card">
<h4>👤 Conecte-se</h4>
<ul>
<li>
<a href="https://github.com/seu-usuario" target="_blank" rel="noopener noreferrer" title="GitHub">
<i class="fa-brands fa-github"></i> GitHub
</a>
</li>
<li>
<a href="https://linkedin.com/in/seu-usuario" target="_blank" rel="noopener noreferrer" title="LinkedIn">
<i class="fa-brands fa-linkedin"></i> LinkedIn
</a>
</li>
</ul>
</div>
<!-- Card: Referências -->
<div class="footer-card">
<h4>📚 Referências</h4>
<ul>
<li>
<a href="https://kubernetes.io/docs/" target="_blank" rel="noopener noreferrer" title="Documentação oficial do Kubernetes">
<i class="fa-solid fa-book"></i> K8s Docs
</a>
</li>
<li>
<a href="https://hub.docker.com/" target="_blank" rel="noopener noreferrer" title="Registry de imagens Docker">
<i class="fa-brands fa-docker"></i> Docker Hub
</a>
</li>
</ul>
</div>
<!-- Card: Ferramentas -->
<div class="footer-card">
<h4>🛠️ Ferramentas</h4>
<ul>
<li>
<a href="https://excalidraw.com/" target="_blank" rel="noopener noreferrer" title="Diagramas rápidos">
<i class="fa-solid fa-pen-ruler"></i> Excalidraw
</a>
</li>
<li>
<a href="https://www.canva.com/" target="_blank" rel="noopener noreferrer" title="Design para documentação">
<i class="fa-solid fa-palette"></i> Canva
</a>
</li>
</ul>
</div>
</div>
---
> **Nota de Manutenção:** Esta wiki segue a filosofia *"Gardening, not Architecture"*. O conteúdo evolui organicamente. Encontrou algo desatualizado? Edite a página ou adicione a tag `#precisa-revisao`.
Seguindo este guia, você terá uma instância do Wiki.js robusta, segura e com uma homepage profissional e organizada. A estrutura modular com Docker e Nginx facilita a manutenção e a escalabilidade, enquanto as personalizações de front-end proporcionam uma experiência de usuário rica e intuitiva. Este documento serve como um ponto de partida sólido para a construção de uma base de conhecimento colaborativa e eficaz.