Olá a todos.
Este post é a continuação do da semana passada, intitulado: Element.io: A Tua Conversa é Tua, e Não do Departamento de Justiça Americano – Parte 1/2
Agora que já expliquei o meu motivo pelo qual estou a fazer isto,e já vos convenci (ou pelo menos plantei a semente da dúvida). Agora vamos ao prático.
O que vamos montar é isto: um servidor Synapse (o homeserver Matrix de referência), com uma base de dados PostgreSQL porque o SQLite que vem por defeito não é para produção, e a interface web do Element a apontar para o vosso servidor. Tudo via Docker Compose, tudo numa máquina que controlam.
Requisitos mínimos:
- Um servidor Linux (Debian 12 recomendado)
- Docker + Docker Compose instalados
- Um domínio próprio com acesso ao DNS
- Portas 80 e 443 abertas no firewall, preferencialmente por detrás de um reverse proxy caso decidam não utilizar o caddy.
- 2GB RAM, 2 vCPUs — suficiente para uso familiar ou equipa pequena
Vou assumir que o vosso domínio principal é exemplo.pt e que vão expor o servidor em matrix.exemplo.pt, com o Element em chat.exemplo.pt. Substituam pelos vossos valores reais ao longo do guia.
Passo 1 — Estrutura de Diretórios
Comecem por criar a estrutura de ficheiros que vão usar:
mkdir -p ~/matrix/{synapse,postgres,element}
cd ~/matrix
Simples. O Synapse vai guardar a sua configuração e dados em ~/matrix/synapse, o Postgres em ~/matrix/postgres, e o config do Element em ~/matrix/element.
Passo 2 — Gerar a Configuração Inicial do Synapse
Antes de escrever o docker-compose.yml, precisam de gerar o ficheiro de configuração base do Synapse. Façam isto:
docker run -it --rm \
-v ~/matrix/synapse:/data \
-e SYNAPSE_SERVER_NAME=matrix.exemplo.pt \
-e SYNAPSE_REPORT_STATS=no \
matrixdotorg/synapse:latest generate
Este comando arranca um container descartável que gera o homeserver.yaml e as chaves de assinatura em ~/matrix/synapse. O SYNAPSE_REPORT_STATS=no é a minha preferência — não envio estatísticas anónimas para o Matrix.org. Podem por yes se quiserem apoiar o projeto com dados agregados.
Verifiquem que os ficheiros foram criados:
ls ~/matrix/synapse/
# homeserver.yaml matrix.exemplo.pt.log.config matrix.exemplo.pt.signing.key
Passo 3 — O docker-compose.yml
Criem o ficheiro principal:
vi ~/matrix/docker-compose.yml
Conteúdo:
version: "3.8"
services: postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_DB=synapse
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=MUDA_ESTA_PASSWORD_AGORA
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
- matrix_net
synapse:
image: matrixdotorg/synapse:latest
restart: unless-stopped
depends_on:
- postgres
volumes:
- ./synapse:/data networks:
- matrix_net
element:
image: vectorim/element-web:latest
restart: unless-stopped
volumes:
- ./element/config.json:/app/config.json:ro
networks:
- matrix_net
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data
- caddy_config:/config
networks:
- matrix_net
volumes:
caddy_data:
caddy_config:
networks:
matrix_net:
driver: bridge
Algumas notas sobre as escolhas aqui:
Usei Caddy como reverse proxy em vez de Nginx porque o Caddy gere os certificados Let’s Encrypt automaticamente, sem configuração adicional. Para quem não é sysadmin de profissão, isto faz uma diferença enorme. O Nginx funciona igualmente bem, mas requer que configurem o Certbot separadamente — mais um passo, mais um serviço, mais coisas para gerir.
O Postgres 16 em vez do SQLite é obrigatório para qualquer coisa além de testes. O SQLite não aguenta escrita concorrente com a frequência que um servidor Matrix gera.
Passo 4 — Configurar o homeserver.yaml
Agora a parte que requer atenção. Abram o ficheiro de configuração que foi gerado:
vi ~/matrix/synapse/homeserver.yaml
Encontrem a secção da base de dados e substituam o bloco SQLite pelo PostgreSQL:
# Comentem ou apaguem isto:
# database:
# name: sqlite3
# args: # database: /data/homeserver.db
# Adicionem isto em substituição:
database:
name: psycopg2
args:
user: synapse
password: MUDA_ESTA_PASSWORD_AGORA
database: synapse
host: postgres
cp_min: 5
cp_max: 10
A password tem de ser a mesma que puseram na variável POSTGRES_PASSWORD no docker-compose.yml. Não se esqueçam.
Outras configurações importantes no homeserver.yaml:
# Desativar registo público — qualquer pessoa poderia criar conta no vosso servidor
enable_registration: false
# Se quiserem permitir registo por convite ou token, usem isto em vez do acima:
# enable_registration: true
# registration_requires_token: true
# URL pública do servidor
public_baseurl: https://matrix.exemplo.pt/
# Tamanho máximo de uploads (ajustem ao vosso gosto)
max_upload_size: 50M
O enable_registration: false é crítico. Com isto desativado, ninguém cria conta no vosso servidor sem que vocês criem manualmente. Para uso familiar ou empresarial fechado, é o que querem.
Passo 5 — Configurar o Element Web
Criem o ficheiro de configuração do Element:
vi ~/matrix/element/config.json
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.exemplo.pt", "server_name": "matrix.exemplo.pt"
}
},
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1"
],
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"features": {},
"show_labs_settings": true,
"default_theme": "light"
}
Se quiserem apontar o Element para o vosso homeserver por defeito (sem os utilizadores terem de o configurar manualmente), o campo base_url é o que faz isso. Os utilizadores abrem chat.exemplo.pt e já está apontado para o vosso servidor.
Passo 6 — O Caddyfile
O Caddy precisa de saber como fazer o routing. Criem:
vi ~/matrix/Caddyfile
matrix.exemplo.pt {
reverse_proxy /_matrix/* synapse:8008
reverse_proxy /_synapse/client/* synapse:8008
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Strict-Transport-Security "max-age=63072000; includeSubDomains"
X-XSS-Protection "1; mode=block"
}
}
chat.exemplo.pt {
reverse_proxy element:80
header {
X-Content-Type-Options nosniff
X-Frame-Options SAMEORIGIN
Strict-Transport-Security "max-age=63072000; includeSubDomains"
}
}
O Caddy vai automaticamente obter certificados TLS válidos para ambos os domínios via Let’s Encrypt. Não precisam de fazer mais nada — só garantir que os registos DNS apontam para o IP do servidor antes de arrancarem.
Passo 7 — DNS
No vosso registrar/painel DNS, adicionem dois registos A:
matrix.exemplo.pt → IP_DO_VOSSO_SERVIDOR
chat.exemplo.pt → IP_DO_VOSSO_SERVIDOR
Se quiserem que os vossos utilizadores tenham IDs do tipo @nome:exemplo.pt (em vez de @nome:matrix.exemplo.pt), precisam de um passo adicional de delegação — mas isso é tema para um how-to separado.
Passo 8 — Arrancar Tudo (e fazer figas)
cd ~/matrix
docker compose up -d
Aguardem uns 30 segundos e verifiquem se está tudo a correr:
docker compose ps
Devem ver os quatro serviços (postgres, synapse, element, caddy) com estado Up. Para ver os logs do Synapse em tempo real:
docker compose logs -f synapse
Passo 9 — Criar o Primeiro Utilizador
Com enable_registration: false, as contas têm de ser criadas manualmente. Façam assim:
docker compose exec synapse register_new_matrix_user \
-c /data/homeserver.yaml \
http://localhost:8008
O comando vai pedir nome de utilizador, password, e se é administrador (yes para o primeiro utilizador — vão precisar de acesso admin para gerir o servidor).
Depois disto, vão a https://chat.exemplo.pt, façam login com as credenciais que acabaram de criar, e o Element já está a comunicar com o vosso servidor.
Passo 10 — Manutenção e Atualizações
Para atualizar as imagens quando saírem novas versões:
cd ~/matrix
docker compose pull
docker compose up -d
Simples assim. O Docker Compose vai recriar os containers com as novas imagens, mantendo todos os dados nos volumes.
Para backups, o essencial é preservar:
~/matrix/postgres/— a base de dados~/matrix/synapse/— a configuração e as chaves de assinatura (as chaves são especialmente importantes — sem elas não conseguem recuperar o servidor)
O que ficou de fora deste guia
Há coisas que deixei propositadamente de fora para não tornar isto avassalador:
TURN server para chamadas de voz/vídeo: Para chamadas que atravessem NAT (que é a maioria das situações reais), precisam de um servidor TURN. O coturn é a solução standard e tem imagem Docker. Vou escrever sobre isso separadamente.
Bridges para outros serviços: Se quiserem que o vosso Element receba mensagens do WhatsApp, Telegram ou Slack, há bridges para tudo isso. São containers adicionais que se ligam ao Synapse. O mxWhatsApp e o mautrix-telegram são os mais maduros.
Delegação de domínio: Se querem IDs @nome:exemplo.pt em vez de @nome:matrix.exemplo.pt, há um passo de configuração adicional com ficheiros .well-known no domínio raiz.
Element Server Suite Pro: Se estão a avaliar o Element para contexto empresarial mais exigente, a versão Pro da Element HQ adiciona gestão centralizada de utilizadores, políticas de retenção configuráveis e integrações SSO que vão além do que este setup cobre. Para uma PME ou empresa com 50+ utilizadores, vale a pena avaliar.
Se tiverem questões ou ficarem presos em algum passo, deixem um comentário. Isto é exactamente o tipo de coisa que gosto de resolver.
Um abraço, Nuno
Categorias: Segurança · On-premise · How-To’s · Pensamentos · Europe
