Plano de implantação da Webtilde runv.club com copyparty
Arquitetura, instalação, segurança, operação e evolução de uma comunidade de páginas pessoais inspirada nas tildes, mas administrada pela web com copyparty.
Plano da Webtilde runv.club com copyparty
Este documento descreve um experimento comunitário inspirado em tilde, pubnix, small web e hospedagem pessoal clássica, mas com uma diferença deliberada: no primeiro estágio, os membros não recebem uma conta Unix nem acesso SSH. Cada participante recebe uma área própria para publicar um pequeno site estático e administra os arquivos pelo navegador, WebDAV ou ferramentas compatíveis com o copyparty.
O resultado não deve ser vendido como uma pubnix completa. O nome tecnicamente honesto é webtilde: uma comunidade de páginas pessoais com identidade, diretório de membros, páginas atualizadas recentemente, webring, regras comuns e sensação de vizinhança digital.
A proposta não é criar “mais uma hospedagem grátis”. É criar um lugar pequeno, reconhecível e humano, no qual cada membro possua um canto da web e consiga publicá-lo sem depender de Git, terminal ou plataforma comercial.
Resumo executivo
A implementação recomendada usa duas instâncias independentes do copyparty:
- Editor autenticado em
party.runv.club. - Servidor público somente leitura em
pages.runv.club.
Ambas enxergam os mesmos diretórios dos membros, porém com permissões diferentes:
- o editor monta os arquivos com leitura e escrita;
- o publicador monta os mesmos arquivos como somente leitura;
- HTML enviado por usuários não é executado dentro da origem autenticada;
- os sites públicos são servidos com a permissão
h, que entregaindex.htmle não exibe a listagem normal de diretórios; - JavaScript permanece desabilitado durante o piloto;
- o proxy reverso é o único componente exposto à internet.
Essa separação é a decisão mais importante de todo o projeto. Executar a interface administrativa e o HTML arbitrário dos membros no mesmo domínio seria uma economia burra: reduz containers, mas aumenta desnecessariamente a superfície de ataque.
O que este experimento será
A Webtilde oferecerá:
- uma página pessoal por membro;
- endereço público no formato
pages.runv.club/~usuario/; - edição e upload por navegador;
- possibilidade de WebDAV para usuários mais técnicos;
- HTML e CSS artesanais;
- imagens, fontes, áudio curto e pequenos arquivos estáticos;
- uma página inicial comunitária;
- diretório de membros;
- páginas recentemente atualizadas;
- botão de página aleatória;
- webring interno;
- feed RSS coletivo de atualizações;
- regras, documentação e modelos iniciais;
- quotas previsíveis por membro;
- aprovação manual de inscrições no piloto;
- backup e restauração testados.
O que este experimento não será
Na primeira versão, ele não fornecerá:
- shell Unix;
- SSH interativo;
- processos persistentes;
cronindividual;- execução de PHP, Python, Node.js ou CGI;
- banco de dados por usuário;
- portas de rede particulares;
- containers individuais;
- e-mail Unix;
- compiladores no servidor;
- Git executado no servidor;
- sincronização bidirecional estilo Dropbox;
- construtor visual de sites;
- WordPress ou qualquer CMS dinâmico.
Isso significa que a Webtilde será uma experiência de publicação comunitária, não uma máquina Unix compartilhada. Uma fase futura poderá conectar a mesma comunidade a contas Debian reais, sem jogar fora a camada web criada agora.
Princípios do projeto
Simplicidade visível
O usuário deve conseguir publicar o primeiro site em poucos minutos, sem conhecer Linux. O onboarding começa com um index.html funcional, uma folha de estilo simples e instruções curtas.
Estrutura de arquivos normal
Os sites permanecem em diretórios comuns do sistema. Não existe importação para armazenamento proprietário nem banco obrigatório para guardar o conteúdo.
Separação entre edição e publicação
A interface de edição nunca deve compartilhar domínio, cookies ou permissões com as páginas públicas.
Poucos privilégios
O container público recebe os arquivos como somente leitura. O container editor roda com usuário sem privilégios e só escreve na árvore destinada aos membros.
Comunidade antes de recursos
Diretório, páginas recentes, webring, regras claras e projetos coletivos são mais importantes do que adicionar cinquenta protocolos.
Evolução por fases
A primeira versão deve ser pequena, reversível e observável. Recursos perigosos — principalmente JavaScript de usuários e contas Unix reais — entram apenas depois que o modelo básico estiver estável.
Arquitetura proposta
INTERNET
│
▼
Nginx / Caddy / Pangolin
TLS + limites + logs
│ │
party.runv.club pages.runv.club
│ │
▼ ▼
copyparty-editor copyparty-pages
autenticado público
leitura/escrita somente leitura
│ │
└────────┬────────┘
▼
/srv/webtilde/users/
├── alice/public_html/
├── bruno/public_html/
└── pablo/public_html/
│
▼
gerador do portal comunitário
membros + recentes + RSS + webring
Componentes
| Componente | Responsabilidade | Exposição |
|---|---|---|
| Debian 13 | Sistema-base, armazenamento e serviços | Administração restrita |
| Docker Engine + Compose | Isolamento e atualização das instâncias | Não exposto diretamente |
copyparty-editor |
Login, upload, renomeação e edição | party.runv.club |
copyparty-pages |
Servir os sites estáticos | pages.runv.club |
| Proxy reverso | HTTPS, domínios, IP real, limites e cabeçalhos | Portas 80/443 |
| Registro de membros | Fonte de verdade de usuários e estado | Somente administrador |
| Gerador do portal | Diretório, recentes, página aleatória e RSS | Publicado como site estático |
| Restic ou Borg | Backup versionado e restauração | Destino externo |
| Prometheus ou logs | Visibilidade operacional | Restrito |
Domínios sugeridos
| Função | Endereço sugerido |
|---|---|
| Portal comunitário | tilde.runv.club ou runv.club |
| Editor e arquivos | party.runv.club |
| Sites dos membros | pages.runv.club/~usuario/ |
| Documentação | help.runv.club ou uma seção do portal |
| Estado do serviço | status.runv.club |
Os nomes são propostas. A exigência arquitetural é manter o editor e os sites publicados em origens diferentes.
Estrutura de armazenamento
/opt/webtilde/
├── compose.yaml
├── .env
├── config/
│ ├── editor/
│ │ ├── copyparty.conf
│ │ └── generated/
│ │ ├── accounts.conf
│ │ └── volumes.conf
│ └── pages/
│ ├── copyparty.conf
│ └── generated/
│ └── volumes.conf
├── state/
│ ├── editor/
│ └── pages/
├── registry/
│ └── members.tsv
├── scripts/
│ ├── add-member.sh
│ ├── suspend-member.sh
│ ├── remove-member.sh
│ ├── render-config.py
│ ├── build-community.py
│ ├── validate-sites.sh
│ └── backup.sh
├── templates/
│ └── starter-site/
└── backups/
/srv/webtilde/users/
├── alice/
│ └── public_html/
│ ├── index.html
│ ├── style.css
│ └── assets/
├── bruno/
│ └── public_html/
└── pablo/
└── public_html/
O diretório /srv/webtilde/users contém conteúdo dos membros. /opt/webtilde contém infraestrutura, configuração e automação. Misturar ambos torna backup, permissões e restauração mais confusos.
Modelo de identidade
Fonte de verdade
O projeto deve manter um registro simples e legível, inicialmente em TSV:
username display_name email status created_at quota_mb
alice Alice alice@example.invalid active 2026-07-13 100
bruno Bruno bruno@example.invalid active 2026-07-13 100
Esse arquivo não é servido publicamente. O e-mail pode ser omitido do portal comunitário e deve existir apenas para administração.
Regras de nome de usuário
Formato recomendado:
^[a-z][a-z0-9_-]{1,30}$
Regras adicionais:
- sempre minúsculo;
- entre 2 e 31 caracteres;
- sem ponto;
- sem espaço;
- sem acento;
- não permitir nomes reservados;
- não permitir nomes visualmente enganosos;
- nome não é reciclado imediatamente após remoção.
Nomes reservados mínimos:
admin
api
assets
help
login
logout
members
new
random
recent
root
rss
static
status
support
www
Senhas
As senhas não devem aparecer em texto puro nos arquivos versionados. O copyparty oferece hashing de senhas; o plano usa Argon2 quando disponível na imagem instalada.
Fluxo recomendado:
- gerar uma senha inicial aleatória;
- gerar o hash usando a própria versão do copyparty em produção;
- gravar apenas o hash na configuração;
- entregar a senha por canal separado;
- permitir troca pelo usuário;
- invalidar a credencial no momento da suspensão.
Nunca coloque a senha real em exemplos, tickets, logs ou repositório Git.
Modelo de publicação
Endereço público
Cada usuário recebe:
https://pages.runv.club/~alice/
O caminho físico correspondente é:
/srv/webtilde/users/alice/public_html/
Arquivo inicial
No momento da criação da conta, o sistema copia um site inicial:
public_html/
├── index.html
├── style.css
├── README.txt
└── assets/
O index.html inicial deve ser curto, editável e sem framework. Um modelo excessivamente sofisticado ensina o usuário a ter medo de mexer nele.
Tipos de conteúdo permitidos no piloto
.html;.css;- imagens web comuns;
.txt;.mdcomo arquivo para download, não como aplicação;- fontes locais em formatos web;
- pequenos áudios, desde que respeitem a quota;
- favicon e manifesto estático.
Conteúdo bloqueado ou não suportado
- executáveis;
- scripts de servidor;
- PHP;
- CGI;
- binários grandes;
- arquivos de banco de dados;
- backups privados;
- dumps SQL;
- chaves, tokens e arquivos
.env; - conteúdo ilegal ou abusivo;
- páginas que tentem imitar o login da própria comunidade.
O bloqueio deve existir em três camadas: regras comunitárias, validação automatizada e configuração do proxy. Nenhuma camada isolada é suficiente.
Segurança da origem web
Por que não usar uma única instância
Uma única instância seria capaz de editar e servir os arquivos, mas criaria um problema conceitual: o domínio autenticado teria contato direto com HTML e SVG controlados pelos membros.
O desenho recomendado evita isso:
party.runv.club
└── interface autenticada
└── HTML do usuário tratado como arquivo/texto, não como página confiável
pages.runv.club
└── conteúdo público
└── container sem escrita e sem credenciais administrativas
Política de JavaScript
Durante o piloto, JavaScript de membros deve permanecer desabilitado por CSP e pelo noscript do copyparty.
Razões:
- todos os membros usam inicialmente a mesma origem
pages.runv.club; - JavaScript de um membro poderia tentar interagir com conteúdo de outro membro na mesma origem;
- cookies e armazenamento local também pertencem à origem, não ao caminho;
- permitir scripts agora cria complexidade sem melhorar a essência do experimento.
HTML e CSS já permitem páginas pessoais excelentes. JavaScript entra apenas quando houver isolamento por subdomínio, por exemplo:
alice.pages.runv.club
bruno.pages.runv.club
Conteúdo na interface de edição
No editor, aplique nohtml aos volumes dos membros. Isso faz HTML e SVG serem tratados de forma conservadora e também reduz riscos ligados à renderização de Markdown.
Além disso:
- desative prologues e epilogues;
- desative renderização automática de README na interface;
- não permita arquivos ocultos por padrão;
- não ofereça upload anônimo;
- não exponha FTP, TFTP, SMB ou SFTP durante o piloto;
- mantenha apenas HTTP interno atrás do proxy HTTPS.
Links simbólicos
Sites de usuários não devem poder escapar da própria árvore por symlink.
Medidas:
- container com bind mount limitado;
- volume público montado como somente leitura;
- validação periódica de symlinks;
- rejeição de links que apontem para fora da pasta;
- nenhuma montagem de
/,/etc,/homeou socket Docker dentro dos containers.
Montar /var/run/docker.sock seria uma falha crítica. Não existe justificativa para isso neste projeto.
Quotas iniciais
Para o piloto:
| Limite | Valor inicial | Justificativa |
|---|---|---|
| Espaço por membro | 100 MiB | Suficiente para HTML, CSS e imagens otimizadas |
| Quantidade de arquivos | 2.000 | Evita milhões de arquivos pequenos |
| Tamanho por arquivo | 25 MiB | Impede uso como depósito de vídeo e backup |
| Espaço livre mínimo global | 5 GiB | Evita preencher completamente o filesystem |
| Membros do piloto | 5 a 10 | Permite observar abuso e ergonomia |
| Duração da fase fechada | 30 dias | Tempo suficiente para testar operação real |
O copyparty oferece flags como sz, df, vmaxb e vmaxn. Os limites totais por volume dependem de indexação, por isso o volume do editor deve usar e2ds.
A quota deve ser revisada com dados reais. Começar com 1 GiB por pessoa seria generoso, mas operacionalmente preguiçoso: incentiva transformar a comunidade em file host antes de provar o conceito.
Instalação no Debian
Pré-requisitos
- Debian 13 atualizado;
- domínio sob seu controle;
- proxy reverso funcional;
- Docker Engine instalado pelo repositório oficial;
- plugin Docker Compose;
- backup externo disponível;
- firewall permitindo publicamente apenas 80/443 e a porta SSH administrativa;
- usuário administrador com
sudoou sessão root consciente.
1. Criar usuário e diretórios
sudo useradd \
--system \
--home-dir /srv/webtilde \
--create-home \
--shell /usr/sbin/nologin \
webtilde
sudo install -d -o webtilde -g webtilde -m 0750 \
/srv/webtilde/users
sudo install -d -o root -g webtilde -m 0750 \
/opt/webtilde \
/opt/webtilde/config/editor/generated \
/opt/webtilde/config/pages/generated \
/opt/webtilde/registry \
/opt/webtilde/scripts \
/opt/webtilde/templates/starter-site \
/opt/webtilde/backups
sudo install -d -o webtilde -g webtilde -m 0750 \
/opt/webtilde/state/editor \
/opt/webtilde/state/pages
WT_UID="$(id -u webtilde)"
WT_GID="$(id -g webtilde)"
sudo tee /opt/webtilde/.env >/dev/null <<EOF_ENV
WT_UID=${WT_UID}
WT_GID=${WT_GID}
TZ=America/Sao_Paulo
EOF_ENV
sudo chmod 0640 /opt/webtilde/.env
sudo chown root:webtilde /opt/webtilde/.env
2. Criar o Compose
A versão abaixo é fixada em 1.20.18 para tornar a implantação reproduzível. Antes da instalação real, confira a versão estável atual e os avisos de segurança; não troque silenciosamente por latest.
services:
editor:
image: copyparty/ac:1.20.18
container_name: webtilde-editor
restart: unless-stopped
init: true
user: "${WT_UID}:${WT_GID}"
ports:
- "127.0.0.1:3923:3923"
volumes:
- ./config/editor:/cfg:ro
- ./state/editor:/state:rw
- /srv/webtilde/users:/w/users:rw
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid,size=256m
environment:
TZ: ${TZ}
pages:
image: copyparty/ac:1.20.18
container_name: webtilde-pages
restart: unless-stopped
init: true
user: "${WT_UID}:${WT_GID}"
ports:
- "127.0.0.1:3924:3923"
volumes:
- ./config/pages:/cfg:ro
- ./state/pages:/state:rw
- /srv/webtilde/users:/w/users:ro
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid,size=256m
environment:
TZ: ${TZ}
Salve como:
/opt/webtilde/compose.yaml
3. Configurar o editor
Arquivo:
/opt/webtilde/config/editor/copyparty.conf
Conteúdo proposto:
[global]
p: 3923
name: runv Webtilde Editor
hist: /state/hists
no-robots
no-logues
no-readme
ah-alg: argon2
chpw
chpw-db: /state/chpw.json
rproxy: 1
xff-hdr: x-forwarded-for
% /cfg/generated
Observações:
- mudanças no bloco global exigem reinício;
- contas e volumes gerados podem ser recarregados;
- o proxy precisa encaminhar corretamente o cabeçalho de IP usado;
- confirme a sintaxe exata com a versão instalada antes de abrir o serviço;
- não relaxe CORS nem habilite
allow-csrf.
4. Configurar o publicador
Arquivo:
/opt/webtilde/config/pages/copyparty.conf
Conteúdo proposto:
[global]
p: 3923
name: runv Webtilde Pages
hist: /state/hists
no-logues
no-readme
rproxy: 1
xff-hdr: x-forwarded-for
% /cfg/generated
O publicador não precisa conter contas dos membros. Sua função é exclusivamente servir os volumes aprovados.
5. Exemplo de configuração gerada do editor
Arquivo:
/opt/webtilde/config/editor/generated/accounts.conf
[accounts]
admin: <HASH_ARGON2_DO_ADMINISTRADOR>
alice: <HASH_ARGON2_DA_ALICE>
Arquivo:
/opt/webtilde/config/editor/generated/volumes.conf
[/u/alice/site]
/w/users/alice/public_html
accs:
rwmd: alice
A: admin
flags:
e2ds
nohtml
sz: 1b-25m
df: 5g
vmaxb: 100m
vmaxn: 2k
Interpretação:
alicepode ler, escrever, mover e apagar dentro do próprio site;adminpossui acesso administrativo;nohtmlprotege a interface de edição contra renderização ativa do conteúdo;e2dsmantém o índice necessário para quotas totais;- a quota é aplicada no volume daquele membro.
6. Exemplo de configuração gerada do publicador
Arquivo:
/opt/webtilde/config/pages/generated/volumes.conf
[/~alice]
/w/users/alice/public_html
accs:
h: *
flags:
noscript
A permissão h faz o volume agir como hospedagem web tradicional: entrega index.html e não oferece a listagem normal da pasta.
O bind mount :ro no Compose é tão importante quanto a permissão interna. Mesmo que uma configuração futura seja escrita incorretamente, o container público ainda não deve conseguir alterar os arquivos.
7. Validar configuração e iniciar
cd /opt/webtilde
sudo docker compose config
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=100 editor
sudo docker compose logs --tail=100 pages
curl -I http://127.0.0.1:3923/
curl -I http://127.0.0.1:3924/~alice/
Não publique os domínios antes de confirmar:
- containers estáveis;
- ausência de erro de permissão;
- login funcionando no editor;
- usuário sem acesso ao volume de outro membro;
- site público funcionando sem autenticação;
- tentativa de escrita no container público falhando;
- HTML no editor não executando;
- JavaScript do site público bloqueado durante o piloto.
Proxy reverso
Regras essenciais
O proxy deve:
- terminar TLS;
- enviar
Hostcorreto; - enviar IP real do cliente;
- enviar protocolo original;
- desativar buffering de upload quando necessário;
- aceitar uploads maiores que o padrão do Nginx;
- usar timeouts suficientes para conexões lentas;
- não expor diretamente as portas 3923 e 3924;
- manter editor e páginas em virtual hosts distintos.
Exemplo para o editor
server {
listen 443 ssl http2;
server_name party.runv.club;
client_max_body_size 32m;
location / {
proxy_pass http://127.0.0.1:3923;
proxy_http_version 1.1;
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_request_buffering off;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Exemplo para as páginas públicas
server {
listen 443 ssl http2;
server_name pages.runv.club;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'none'; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'none'" always;
location ~* /(?:\.git|\.svn|\.hg)(?:/|$) {
return 404;
}
location ~* \.(?:env|ini|log|sql|bak|swp|tmp)$ {
return 404;
}
location / {
proxy_pass http://127.0.0.1:3924;
proxy_http_version 1.1;
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_buffering off;
proxy_read_timeout 300s;
}
}
A configuração de certificado depende do proxy já usado na infraestrutura. Não copie uma configuração TLS genérica por cima de um ambiente que já usa Pangolin, Traefik, Caddy ou CloudPanel.
Automação de membros
Script add-member
O processo de criação deve ser idempotente e executar, nesta ordem:
- validar o nome de usuário;
- verificar nomes reservados;
- confirmar que o usuário não existe;
- criar diretório temporário;
- copiar o site inicial;
- aplicar proprietário e modo corretos;
- adicionar o membro ao registro;
- gerar hash da senha;
- reconstruir as configurações;
- validar as configurações geradas;
- mover o diretório para o local definitivo;
- recarregar editor e publicador;
- testar URLs;
- registrar a operação;
- entregar credenciais e documentação.
Recarregar sem derrubar uploads
Depois de alterar apenas contas ou volumes:
sudo docker kill --signal=USR1 webtilde-editor
sudo docker kill --signal=USR1 webtilde-pages
Mudanças globais exigem recriação ou reinício controlado:
cd /opt/webtilde
sudo docker compose up -d --force-recreate editor pages
Suspensão
Suspender não significa apagar imediatamente.
O script deve:
- marcar
status=suspendedno registro; - remover a conta do editor;
- remover ou substituir o volume público por página de suspensão;
- manter os arquivos preservados;
- recarregar a configuração;
- registrar motivo e data;
- definir prazo de recurso ou remoção.
Remoção
A remoção definitiva deve exigir uma segunda ação administrativa e um backup anterior.
Fluxo recomendado:
active → suspended → archived → deleted
Não implemente um botão que apaga árvore de usuário diretamente a partir de uma requisição web. Isso seria uma forma desnecessariamente elegante de perder dados.
Portal comunitário
O copyparty cuida dos arquivos, mas não cria sozinho a cultura da comunidade. Um pequeno gerador estático deve construir o portal.
Páginas mínimas
/
/about/
/join/
/rules/
/help/
/members/
/recent/
/random/
/projects/
webring/
feed.xml
Diretório de membros
Cada entrada pode exibir:
- nome público;
~username;- título extraído do HTML;
- descrição opcional;
- data da última atualização;
- tags escolhidas pelo membro;
- link para o site;
- indicação de novo membro.
Não exiba e-mail, IP, quota, nome civil obrigatório ou estatísticas invasivas.
Atualizações recentes
O gerador pode usar a data de modificação dos arquivos ou, preferencialmente, um estado próprio atualizado pelo hook de publicação.
Regras úteis:
- ignorar alterações de arquivos temporários;
- agrupar várias mudanças do mesmo membro;
- não revelar nomes de arquivos privados;
- limitar uma entrada por membro em cada janela de tempo;
- não transformar atividade em ranking competitivo.
Página aleatória
O botão “visitar uma página aleatória” é pequeno, mas essencial. Ele faz a comunidade parecer um lugar navegável, não uma tabela de contas.
Webring
Cada site inicial recebe links “anterior”, “aleatório” e “próximo”. O gerador recalcula a ordem a partir dos membros ativos.
RSS coletivo
O feed deve publicar somente eventos de atualização, por exemplo:
Alice atualizou sua página pessoal.
Bruno publicou um novo projeto.
Pablo alterou a seção de leituras.
Não copie o conteúdo integral dos sites sem consentimento.
Experiência do membro
Primeiro acesso
O membro recebe:
Seu site: https://pages.runv.club/~alice/
Editor: https://party.runv.club/u/alice/site/
Ajuda: https://help.runv.club/
O tutorial inicial deve pedir apenas:
- entrar no editor;
- abrir
index.html; - alterar título e apresentação;
- salvar;
- abrir a página pública;
- editar
style.css; - adicionar uma imagem otimizada.
Fluxo cotidiano
login no editor
→ editar ou enviar arquivos
→ salvar
→ página pública muda imediatamente
→ gerador comunitário registra atualização
Não é necessário um processo separado de “deploy” no MVP. A pasta editada é a mesma pasta que o publicador lê, com permissões de montagem diferentes.
WebDAV opcional
Depois que a interface web estiver estável, usuários podem conectar via WebDAV ao editor. Isso permite uso por gerenciadores de arquivos e editores locais.
Não habilite simultaneamente FTP, SFTP, SMB e TFTP só porque o software oferece. Cada protocolo adicional aumenta documentação, suporte e superfície de ataque. Web e WebDAV cobrem o experimento inicial.
Regras comunitárias mínimas
A política precisa ser curta o bastante para ser lida e clara o bastante para ser aplicada.
Permitido
- páginas pessoais;
- projetos experimentais;
- ensaios, diários e blogs estáticos;
- arte digital;
- coleções pequenas e legais;
- CSS estranho;
- estética retro, minimalista ou maximalista;
- links para outros espaços pessoais;
- conteúdo em qualquer idioma, desde que moderável.
Proibido
- malware;
- phishing;
- mineração no navegador;
- rastreamento abusivo;
- hospedagem de material ilegal;
- assédio e exposição de dados pessoais;
- cópia massiva de conteúdo protegido;
- usar a quota como CDN comercial;
- uso como espelho de backups;
- tentativa de explorar outros membros ou a infraestrutura;
- páginas que falsifiquem o login da comunidade.
Privacidade
Deixe explícito:
- administradores conseguem acessar arquivos hospedados;
- os sites são públicos;
- logs técnicos existem;
- backups retêm versões por período definido;
- não existe promessa de anonimato forte;
- o serviço não deve receber segredos ou documentos privados.
Monitoramento
O que observar
- estado dos dois containers;
- respostas HTTP do editor e do publicador;
- espaço livre;
- tamanho total dos sites;
- quantidade de arquivos;
- falhas de login;
- erros 5xx;
- tempo de resposta;
- filas ou uploads incompletos;
- alterações inesperadas de configuração;
- presença de symlinks perigosos;
- resultado do backup mais recente;
- idade do último teste de restauração.
Alertas mínimos
- disco abaixo de 15% livre;
- container reiniciando repetidamente;
- domínio sem responder;
- backup diário ausente;
- certificado próximo do vencimento;
- aumento anormal de tráfego;
- alteração do registro de membros fora do processo normal;
- arquivo maior que o permitido aparecendo no filesystem.
Logs sem revisão são decoração técnica. Defina retenção e alertas desde o piloto.
Backup e restauração
O que precisa ser salvo
/srv/webtilde/users/
/opt/webtilde/config/
/opt/webtilde/registry/
/opt/webtilde/scripts/
/opt/webtilde/templates/
/opt/webtilde/compose.yaml
/opt/webtilde/.env
O estado de índices do copyparty pode ser reconstruído, mas salvá-lo pode acelerar recuperação. Credenciais e arquivos de ambiente exigem criptografia no destino.
Política inicial
| Camada | Frequência | Retenção |
|---|---|---|
| Snapshot local | A cada 6 horas | 7 dias |
| Backup externo incremental | Diário | 30 dias |
| Backup mensal | Mensal | 12 meses |
| Teste de restauração | Mensal | Relatório obrigatório |
Teste real
Uma restauração válida não é “o comando terminou sem erro”. Ela deve comprovar:
- recuperação de um usuário específico;
- recuperação do registro;
- reconstrução das configurações;
- inicialização dos containers;
- acesso ao site restaurado;
- login no editor;
- preservação de proprietário e permissões.
Atualizações
Política
- fixar versão da imagem;
- acompanhar releases e advisories;
- testar atualização em cópia ou ambiente de staging;
- ler mudanças de configuração;
- fazer backup antes da atualização;
- atualizar um componente por vez;
- validar login, upload, publicação e quotas;
- manter procedimento de rollback.
Procedimento sugerido
cd /opt/webtilde
sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps
sudo docker compose logs --tail=100 editor pages
Esse comando só deve ser executado depois de alterar conscientemente a tag da imagem no Compose. pull não é política de atualização; é apenas transporte.
A versão 1.20.18, publicada em julho de 2026, aparece neste documento como referência pesquisada. O projeto havia corrigido uma vulnerabilidade relevante na versão anterior, o que reforça a necessidade de acompanhar advisories e não abandonar o serviço em uma tag antiga.
Plano de testes
Isolamento entre usuários
- Alice não vê o volume de Bruno;
- Alice não baixa arquivo de Bruno pelo editor;
- Alice não move arquivo para pasta de Bruno;
- URL manipulada manualmente retorna negação;
- conta suspensa perde acesso imediatamente.
Publicação
index.htmlé entregue na raiz do usuário;- não existe listagem de diretórios;
- CSS e imagens carregam;
- página sem
index.htmlfalha de maneira previsível; - arquivos proibidos são bloqueados;
- JavaScript não executa no piloto.
Permissões do container
- o publicador não consegue criar arquivo;
- nenhum container enxerga
/etcdo host; - nenhum container recebe socket Docker;
- processo roda com UID/GID do usuário
webtilde; - capacidades Linux foram removidas;
- portas internas escutam apenas em loopback.
Quotas
- arquivo acima de 25 MiB é rejeitado;
- volume acima de 100 MiB é bloqueado;
- volume acima de 2.000 arquivos é bloqueado;
- reserva mínima de disco é respeitada;
- rejeição não corrompe arquivos existentes.
Proxy
- HTTP redireciona para HTTPS;
- IP real aparece corretamente nos logs;
- upload grande não falha por buffering;
- cabeçalho CSP chega intacto ao navegador;
- HSTS só é ativado depois que todos os subdomínios estiverem corretos;
- portas 3923 e 3924 não são acessíveis externamente.
Recuperação
- apagar um arquivo e restaurá-lo;
- restaurar um site completo;
- reconstruir container em host limpo;
- recriar configuração a partir do registro;
- medir o tempo real de recuperação.
Fases do projeto
Fase 0 — prova local
Duração sugerida: 1 a 3 dias.
Objetivos:
- duas instâncias funcionando;
- um usuário fictício;
- proxy local ou hosts file;
nohtml,noscriptehvalidados;- tentativa de acesso cruzado testada;
- configuração descartável.
Critério de saída: arquitetura comprovada sem domínio público.
Fase 1 — alpha fechado
Duração sugerida: 30 dias.
Escopo:
- 5 a 10 membros conhecidos;
- aprovação manual;
- 100 MiB por membro;
- HTML e CSS;
- JavaScript bloqueado;
- portal comunitário básico;
- backup diário;
- canal único de suporte.
Critérios de sucesso:
- pelo menos 80% publicam sem intervenção manual longa;
- nenhum acesso cruzado;
- nenhum incidente crítico;
- restauração testada;
- onboarding administrativo abaixo de cinco minutos;
- documentação resolve as dúvidas mais repetidas.
Fase 2 — beta público controlado
Escopo:
- formulário de inscrição;
- fila de aprovação;
- termos e política de privacidade;
- automação de contas;
- página de status;
- moderação documentada;
- métricas e alertas;
- até 50 membros.
Critério de saída: processo sustentável sem depender de improviso diário do administrador.
Fase 3 — subdomínios por membro
Modelo:
alice.pages.runv.club
bruno.pages.runv.club
Benefícios:
- origem separada por membro;
- possibilidade de JavaScript com risco reduzido entre usuários;
- cookies e armazenamento local isolados;
- identidade mais forte para os sites.
Custos:
- wildcard DNS e certificado;
- roteamento por hostname;
- validação mais rigorosa de nomes;
- mais testes de cache, CSP e proxy;
- prevenção de subdomínios reservados.
JavaScript só deve ser considerado depois dessa fase.
Fase 4 — ponte para uma tilde Unix real
A comunidade pode ganhar contas Debian e SSH mantendo o copyparty como interface opcional.
/home/alice/public_html
▲ ▲
│ │
SSH copyparty
Essa fase adiciona:
- usuários Unix reais;
- shell;
- Git;
- editores de terminal;
- quotas de filesystem;
- limites de processos;
- política de execução;
- maior superfície de abuso.
Não tente implementar isso no mesmo dia da Webtilde. São produtos operacionalmente diferentes.
Riscos e respostas
| Risco | Impacto | Resposta |
|---|---|---|
| XSS no editor | Roubo de sessão administrativa | Origem separada + nohtml + sem upload anônimo |
| Script de um membro atinge outro | Interferência entre sites | JavaScript bloqueado até subdomínios isolados |
| Disco cheio | Queda do serviço e corrupção | Quotas + df + alertas + filesystem separado |
| Configuração manual inconsistente | Acesso cruzado | Registro único + gerador idempotente + testes |
| Apagar usuário por engano | Perda de conteúdo | Suspensão antes de remoção + backup |
| Symlink escapando da pasta | Exposição do host | Bind mounts mínimos + varredura + container sem privilégios |
| Versão vulnerável | Comprometimento remoto | Tags fixas + advisories + atualização testada |
| Projeto vira depósito de arquivos | Custo e abuso | 100 MiB + 25 MiB por arquivo + regras claras |
| Administrador vira gargalo | Projeto abandona usuários | Scripts, documentação, métricas e onboarding previsível |
| Confusão com pubnix completa | Expectativa errada | Chamar de Webtilde e explicar limites desde o início |
Decisões que eu não recomendo
- uma única instância para editar e servir;
- usar
latestsem revisão; - permitir upload anônimo;
- liberar JavaScript na origem compartilhada;
- montar o disco inteiro no container;
- rodar como root;
- abrir todos os protocolos do copyparty;
- oferecer 5 ou 10 GiB por usuário sem necessidade;
- gerar configuração manualmente para dezenas de membros;
- confiar em backup nunca restaurado;
- chamar o experimento de “tilde Unix completa” quando não existe shell;
- adicionar banco, painel React e fila de jobs antes de provar o fluxo básico.
A última armadilha é especialmente comum: transformar um experimento simples de páginas pessoais em uma plataforma SaaS caseira antes de existir uma comunidade. O software passa a consumir toda a energia e a parte humana nunca nasce.
Métricas de sucesso
Técnicas
- disponibilidade mensal;
- tempo médio de criação de conta;
- quantidade de erros de permissão;
- taxa de sucesso de upload;
- restaurações testadas;
- uso de disco por membro;
- número de incidentes de segurança;
- tempo de atualização da configuração.
Comunitárias
- membros que alteraram o site inicial;
- páginas atualizadas no último mês;
- visitas pelo botão aleatório;
- participação em projetos coletivos;
- inscrições aprovadas que realmente publicaram;
- dúvidas recorrentes que indicam falha de documentação;
- membros que continuam ativos após 30 e 90 dias.
Não use pageviews como única métrica. Uma webtilde com vinte páginas cuidadas e vínculos reais é mais bem-sucedida do que uma hospedagem com mil contas abandonadas.
Checklist de abertura
Infraestrutura
- Debian atualizado
- Docker e Compose instalados
- usuário
webtildesem shell - filesystem com espaço e monitoramento
- portas internas apenas em loopback
- proxy reverso com TLS
- dois containers separados
- container público com volume somente leitura
- nenhum socket Docker montado
Segurança
-
nohtmlno editor -
noscriptno publicador - permissão
hnos sites - prologues e README automáticos desabilitados
- contas com hashes
- teste de acesso cruzado concluído
- CSP verificada no navegador
- quotas funcionando
- versão sem advisory crítico conhecido
Operação
- script de criação testado
- suspensão testada
- remoção com arquivo testada
- backup externo concluído
- restauração real concluída
- logs e alertas funcionando
- procedimento de atualização documentado
- contato de suporte definido
Comunidade
- nome e descrição honestos
- regras publicadas
- privacidade publicada
- tutorial inicial curto
- site modelo editável
- diretório de membros
- páginas recentes
- página aleatória
- webring
- formulário ou processo de inscrição
Detalhes recolhíveis
Por que não usar volumes dinâmicos por identidade no primeiro dia?
O copyparty possui integração com provedores de identidade e mecanismos de volumes dinâmicos. Isso pode reduzir configuração repetida, mas também aumenta o número de estados implícitos e torna o comportamento de reinicialização e herança de permissões mais difícil de auditar.
Para um piloto com até dez pessoas, gerar explicitamente contas e volumes é menos elegante e muito mais verificável. Depois que o modelo de permissões estiver provado, um IdP pode ser introduzido com testes específicos.
Por que duas instâncias em vez de apenas dois volumes?
Volumes separam caminhos e permissões, mas não criam o mesmo grau de isolamento operacional de processos diferentes. Com duas instâncias:
- a pública não possui credenciais;
- a pública recebe bind mount somente leitura;
- políticas globais podem ser diferentes;
- falha no editor não implica automaticamente escrita pelo publicador;
- logs e atualizações podem ser analisados separadamente;
- o proxy distingue claramente os dois papéis.
O custo é um pouco mais de RAM e dois serviços para acompanhar. Neste caso, a clareza de segurança vale mais do que a economia marginal.
Quando liberar JavaScript?
Somente quando cada membro tiver uma origem independente, idealmente um subdomínio próprio, e depois de validar:
- wildcard DNS;
- certificado wildcard ou automação equivalente;
- isolamento de cookies;
- CSP por site;
- política contra mineração e rastreamento;
- bloqueio de phishing;
- resposta a abuso;
- limites de rede e armazenamento.
Mesmo com subdomínios, JavaScript continua sendo conteúdo ativo de terceiros. A diferença é que o navegador oferece uma fronteira de origem muito mais útil.
Rollback da implantação
cd /opt/webtilde
sudo docker compose down
Esse comando remove os containers e a rede do Compose, mas não deve apagar:
/srv/webtilde/users/
/opt/webtilde/config/
/opt/webtilde/state/
/opt/webtilde/registry/
Antes de qualquer remoção definitiva:
sudo tar -C / -czf /root/webtilde-pre-remove.tar.gz \
opt/webtilde \
srv/webtilde
Esse arquivo local não substitui backup externo. Ele apenas reduz a chance de uma desinstalação apressada virar perda imediata.
Fontes técnicas consultadas
A pesquisa para este plano foi baseada principalmente em fontes primárias:
- repositório oficial
9001/copyparty; - README oficial do copyparty;
- documentação oficial de contas, volumes e permissões;
- documentação oficial das imagens Docker;
- exemplos oficiais de proxy reverso;
- releases e avisos de segurança do projeto;
- documentação do Tilde.club sobre computador Unix compartilhado, páginas pessoais e comunidade;
- documentação oficial do Docker para Debian e Docker Compose.
Pontos incorporados diretamente ao desenho:
- contas e permissões por volume;
- permissão
hpara comportamento de servidor web; nohtmlenoscriptpara conteúdo não confiável;- quotas
sz,df,vmaxbevmaxn; - necessidade de
e2dspara limites totais do volume; - recarga de contas e volumes por
USR1; - uso da imagem Docker
copyparty/ac; - uso de
/cfgpara configurações e/wpara conteúdo; - recomendação de proxy reverso;
- acompanhamento de releases e vulnerabilidades.
Limite desta documentação
Os blocos de configuração são um projeto técnico detalhado e coerente com a documentação pesquisada, mas devem passar por validação em uma máquina de testes antes da abertura pública. Versões futuras podem alterar flags, comportamento de cabeçalhos ou formato de configuração.
Dicas finais
- Comece com dez pessoas, não cem: a parte difícil não é subir o container; é operar comunidade, abuso, restauração e suporte.
- Não libere JavaScript por ansiedade de parecer completo: HTML e CSS bastam para provar a ideia.
- Não misture editor e sites públicos: essa separação deve existir desde a primeira implantação.
- Use um registro como fonte de verdade: configuração gerada é descartável; dados dos membros e registro não são.
- Teste restauração antes de convidar pessoas: depois que alguém cria algo, o projeto passa a ter responsabilidade real.
- Chame de Webtilde: é inspirado em tilde, mas não finge oferecer shell Unix.
- Preserve o caminho para crescer: a mesma pasta
public_htmlpoderá futuramente ser acessada por SSH em uma tilde Debian real. - Resista à plataforma infinita: diretório, página aleatória, webring e bons sites importam mais que um painel administrativo gigantesco.
O melhor primeiro resultado não é uma infraestrutura impressionante. É abrir pages.runv.club/~alguem/ e encontrar uma página estranha, pessoal e claramente feita por uma pessoa.