Self-Hosting - Sumário
▲Introdução
Este é um guia que estou fazendo direcionado a pessoas que querem hospedar sua própria instância do Tabledown, mas obviamente temos inúmeras maneiras de hostear aplicações web atualmente, então nesse guia vou começar com algumas premissas:
- Você quer hospedar uma instância usando uma VPS/Máquina Virtual em alguma plataforma de cloud;
- Você conhece comandos básicos do Linux/pastas Linux, SSH e lidar com DNS. Não vou pedir nada absurdo, mas saber como mover pastas em um terminal Linux, saber como comprar um domínio e redirecionar ele para o seu IP e como se conectar à sua VPS via SSH é essencial, caso você não saiba nada disso, qualquer um desses tópicos pode ser facilmente encontrado online e aprendido em coisa de meia hora;
- Você vai comprar um domínio para ter proteção SSL. Isso não é necessário se seu servidor for acessível apenas para você e amigos próximos, mas assumo que a maioria das pessoas quer ter uma conexão segura;
Crie Uma VPS Em Qualquer Plataforma De Cloud
Qualquer plataforma de cloud terá pelo menos um serviço, que é uma VPS/Máquina Virtual, é exatamente o que precisamos. Gosto de alugar servidores Debian Linux, pois tendem a ser mais estáveis, mas fique à vontade pra escolher o que quiser.
Uma vez que sua VPS esteja adquirida, você provavelmente vai querer abrir algumas rotas TCP primeiro, isso varia muito com o provedor de cloud, mas geralmente você quer encontrar as regras de segurança de rede e abrir algumas portas:
| Protocolo | Tipo | Porta | Direção | Remote CIDR |
|---|---|---|---|---|
| TCP | IPv4 | 80 (HTTP) | IN | * (Qualquer IP) |
| TCP | IPv4 | 443 (HTTPS) | IN | * (Qualquer IP) |
Com isso definido, qualquer IP pode acessar nossas portas para HTTP e HTTPS.
Agora você vai anotar seu IP público YOUR_VPS_IP, também configure suas chaves SSH para se conectar à sua VPS quando necessário;
Conecte-se via SSH para confirmar que você já tem acesso à sua nova máquina (no exemplo abaixo estou usando root como usuário, mas isso pode variar com o provedor de cloud):
ssh root@YOUR_VPS_IP
Aponte Seu Domínio Para A VPS
Você pode pular esta etapa se não quiser ter um domínio para seu servidor nem certificados SSL, mas caso queira, você precisará ir ao registrar de domínios da sua preferência, comprar o domínio que deseja (usarei mydomain.com como referência) e nas configurações do seu domínio no registrar você precisa encontrar onde gerenciar DNS / Nameservers. Então você definirá o DNS do seu domínio para apontar para o IP público da sua VPS.
Adicione estes registros:
| Tipo | Nome | Valor | TTL |
|---|---|---|---|
| A | @ |
YOUR_VPS_IP |
300 |
| A | api |
YOUR_VPS_IP |
300 |
| A | www |
YOUR_VPS_IP |
300 |
O @ cobre mydomain.com e www cobre www.mydomain.com. O subdomínio api cobre api.mydomain.com que usaremos para o backend.
Feito isso, precisamos esperar a propagação do DNS, o que pode levar de alguns minutos a algumas horas.
Preparar A VPS
Supondo que você esteja usando um sistema baseado em Debian para sua VPS, primeiro precisamos atualizar o sistema e depois instalar alguns pacotes:
apt update && apt upgrade -y
apt install -y nginx certbot python3-certbot-nginx docker.io docker-compose git ufw
Com isso temos a maior parte do que usaremos para hospedar o servidor:
- Nginx: O próprio servidor HTTP que fará o reverse-proxy para nossa aplicação;
- Certbot: Para automatizar a renovação dos certificados SSL;
- UFW: Para configurar firewalls;
- Docker: Para executar nossa aplicação em contêineres;
- Git: Bem .... Para fazer coisas de Git;
Agora configuramos os firewalls para SSH e Nginx:
ufw allow OpenSSH
ufw allow 'Nginx Full'
ufw enable
E finalmente iniciamos os serviços do Nginx e Docker:
systemctl enable nginx docker
systemctl start nginx docker
Subindo Sua Aplicação
Agora é hora de clonar o Tabledown na VPS, usarei o repositório principal do Tabledown como exemplo, mas você pode usar seu próprio fork também, obviamente, também clonarei o Tabledown na pasta /opt/tabledown, mas isso é 100% preferência, você pode cloná-lo onde quiser em sua VPS.
Observe também que usarei a versão HTTP do repositório, mas sinta-se à vontade para usar a versão SSH e configurar chaves SSH para sua origem remota do Git em sua VPS.
git clone https://codeberg.org/grepehu/tabledown.git /opt/tabledown
cd /opt/tabledown
docker compose up -d
Variáveis De Ambiente
Agora com o Tabledown clonado, precisamos apenas configurar as variáveis de ambiente adequadamente. No projeto principal temos o .env.example, você pode apenas copiar e colar em um novo arquivo .env e então substituir as variáveis pelos valores apropriados:
- ENV: Isso determina o ambiente em que você está executando,
devpara desenvolvimento onde algumas coisas como CORS serão ignoradas eprodpara o ambiente de produção adequado; - ALLOWED_ORIGIN: Lista de origens de domínio permitidas (incluindo http/https) que podem enviar requisições para seu backend, separadas por vírgula;
- VITE_ENV: Muito parecido com
ENV, exceto que isso só existe no lado do cliente; - VITE_PUBLIC_URL: Este é o domínio onde seu lado do cliente será implantado, no exemplo que estamos usando seria
https://mydomain.com, o lado do cliente usa isso para acessar recursos a partir do caminho absoluto no domínio, fazendo com que os assets carreguem no pre-load do HTML para deixar links muito melhores; - VITE_BACKEND_URL: Este é o endereço do backend que usaremos, neste exemplo seria
https://api.mydomain.com, o lado do cliente usa este endereço para enviar requisições ao backend; - VITE_MORE_URL: Este é o endereço da página inicial com mais informações, geralmente
https://tabledown.neocities.org; - VITE_SHEETS_URL: Essas é a URL que usamos para obter modelos de fichas, deixar estas variável em branco não vai quebrar a aplicação, mas vai tornar a feature de achar fichas prontas inítil. Você pode colocar nesta variável o valor de
/sheets.jsone adicionar um arquivo com o mesmo nome na pastasrc/public/antes de rodar o build da aplicação before building, então seu app terá modelos de fichas localmente salvas; - VERSION: Pode ser deixado vazio, isso só é útil para mim para marcar versões git do projeto, não faz nada para o deploy;
Fichas
Tocamos neste assunto na seção anterior, mas gostaria de ressaltar que VITE_SHEETS_URL é uma variável que aponta para um endereço onde a aplicação espera encontrar um arquivo sheets.json, este endereço pode apontar para qualquer lugar inclusive para dentro da própria aplicação, o objetivo disso e permitir que as fichas sejam atualizadas constantemente sem a necessidade de reconstruir a aplicação pra todo update.
Além disso você pode obter uma versão atual de fichas que usamos em produção em https://codeberg.org/grepehu/tabledown-sheets/src/branch/master/sheets.json, onde você pode baixar este arquivo, adicionar em src/public/ no seu projeto e colocar a variável VITE_SHEETS_URL como /sheets.json, fazendo assim sua aplicação obter as fichas dentro de si mesma.
Gerenciamento Docker
Como o Docker já está instalado no sistema e tendo nosso .env configurado, podemos agora iniciar nossos contêineres com (dentro da pasta tabledown, onde temos o arquivo docker-compose.yml):
docker compose up -d
Isso iniciará um servidor em segundo plano, para futuras atualizações, o que gosto de fazer pessoalmente é puxar as mudanças recentes no git, desligar os contêineres Docker, limpar qualquer coisa dentro do sistema Docker (isso é opcional, mas gosto de fazer para evitar o cache e logs que se acumulam muito rapidamente no Docker) e finalmente iniciar o contêiner novamente:
git pull
docker compose down
docker system prune -a
docker compose up -d
Configurar Nginx
Para lidar com nosso proxy reverso no Nginx, precisaremos criar dois arquivos de configuração:
/etc/nginx/sites-available/mydomain.com
server {
listen 80;
server_name mydomain.com www.mydomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
/etc/nginx/sites-available/api.mydomain.com
server {
listen 80;
server_name api.mydomain.com;
location / {
proxy_pass http://127.0.0.1:3000;
# Necessário para SSE
proxy_buffering off;
proxy_cache off;
proxy_http_version 1.1;
proxy_set_header Connection '';
# Timeouts longos o suficiente para SSE
proxy_read_timeout 24h;
proxy_send_timeout 24h;
keepalive_timeout 24h;
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;
}
}
Observe que especialmente para o backend temos algumas linhas especiais por causa das conexões SSE em tempo real que usamos na aplicação, como timeouts grandes e desativação de buffer.
Tendo esses arquivos escritos, precisamos habilitá-los e recarregar o Nginx:
ln -s /etc/nginx/sites-available/tabledown.net /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/api.tabledown.net /etc/nginx/sites-enabled/
Você pode remover o placeholder antigo do Nginx se quiser:
rm /etc/nginx/sites-enabled/default
Então verificamos se há erros em nossos arquivos de configuração:
nginx -t
E finalmente recarregamos o Nginx:
systemctl reload nginx
SSL Com Let's Encrypt
Quando o DNS tiver se propagado para o IP da sua VPS, podemos ativar o SSL, podemos verificar se o DNS se propagou com:
dig mydomain.com
Se for bem-sucedido, podemos finalmente usar o Certbot para adicionar certificados SSL ao nosso domínio com:
certbot --nginx -d mydomain.com -d www.mydomain.com
certbot --nginx -d api.mydomain.com
O Certbot modificará automaticamente suas configurações do Nginx para adicionar HTTPS e configurar um bloco de servidor 443. Ele também instala um cron job para renovar automaticamente os certificados.
Podemos sempre simular se a renovação do SSL funciona executando um dry test:
certbot renew --dry-run
Quando o SSL estiver pronto, você talvez queira adicionar ao frontend do Nginx uma maneira de redirecionar www. para removê-lo, então no bloco SSL 443 adicione isto abaixo dos nomes de domínio:
if ($host = www.mydomain.com) {
return 301 https://mydomain.com$request_uri; # Redireciona www para removê-lo
}
O trecho acima é opcional, mas importante porque o Tabledown usa local storage para salvar dados do usuário e os navegadores salvam o local storage com base no domínio do site, então usuários acessando www.mydomain.com terão dados diferentes no armazenamento do que mydomain.com.
Quando tudo estiver feito, recarregamos o Nginx:
nginx -t && systemctl reload nginx
Pronto
Agora você provavelmente conseguirá acessar sua aplicação em mydomain.com e ela se comunicará corretamente com o backend em api.mydomain.com.
Apenas uma observação, a configuração do docker-compose para esta aplicação está definida para não salvar nenhum dado das execuções dos contêineres, então a cada reinicialização você perderá todas as salas que estavam lá, o que não é tão ruim considerando que o Tabledown exclui salas a cada 24 horas de qualquer forma, mas se você quiser mudar esse comportamento, você pode modificar o docker-compose.yml como achar melhor.