Cloudflare Workers fornece um runtime rápido e distribuído globalmente para EmDash. Este guia cobre a implantação com D1 para o banco de dados e R2 para armazenamento de mídia.
Pré-requisitos
- Uma conta Cloudflare
- Wrangler CLI instalado (
npm install -g wrangler) - Autenticado com Cloudflare (
wrangler login)
Configurar Bindings
Crie wrangler.jsonc na raiz do seu projeto com bindings D1 e R2. O Wrangler provisiona ambos os recursos na primeira implantação se ainda não existirem.
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-emdash-site",
"compatibility_date": "2025-01-15",
"compatibility_flags": ["nodejs_compat"],
"d1_databases": [
{
"binding": "DB",
"database_name": "emdash-db",
},
],
"r2_buckets": [
{
"binding": "MEDIA",
"bucket_name": "emdash-media",
},
],
}
Configurar EmDash
Atualize sua configuração Astro para usar D1 e R2:
import { defineConfig } from "astro/config";
import cloudflare from "@astrojs/cloudflare";
import emdash from "emdash/astro";
import { d1, r2 } from "@emdash-cms/cloudflare";
export default defineConfig({
output: "server",
adapter: cloudflare(),
integrations: [
emdash({
database: d1({ binding: "DB" }),
storage: r2({ binding: "MEDIA" }),
}),
],
});
Primeira Inicialização
As migrações do banco de dados são executadas automaticamente na primeira solicitação após a implantação, e em cada inicialização subsequente se houver algo novo para aplicar.
Se o banco de dados estiver vazio (sem coleções) e o assistente de configuração não tiver sido concluído, EmDash também aplica um arquivo seed na primeira inicialização. O seed é lido no momento da compilação de .emdash/seed.json, do caminho em package.json#emdash.seed, ou de seed/seed.json — o que for encontrado primeiro — e incorporado ao bundle. Se nenhum estiver presente, um seed padrão integrado é usado. Implantações subsequentes contra um banco de dados existente deixam seu conteúdo intocado.
Implantar
Implante no Cloudflare Workers:
wrangler deploy
Seu site está agora ativo em https://my-emdash-site.<your-subdomain>.workers.dev.
Read Replicas
Para sites distribuídos globalmente, habilite a replicação de leitura D1 para rotear consultas de leitura para réplicas próximas em vez de sempre acessar o banco de dados primário. Isso reduz significativamente a latência para visitantes distantes da região primária.
emdash({
database: d1({
binding: "DB",
session: "auto",
}),
storage: r2({ binding: "MEDIA" }),
}),
Você também precisa habilitar a replicação de leitura no próprio banco de dados D1 no painel do Cloudflare ou via API REST.
Consulte Opções de Banco de Dados — Read Replicas para modos de sessão e como funciona a consistência baseada em marcadores.
Domínio Personalizado
Adicione um domínio personalizado no painel do Cloudflare:
- Vá para Workers & Pages > seu worker
- Clique em Custom Domains > Add Custom Domain
- Digite seu domínio e siga as instruções de configuração DNS
Acesso Público R2
Para servir mídia diretamente do R2 (recomendado para desempenho):
- No painel do Cloudflare, vá para R2 > seu bucket
- Clique em Settings > Public access
- Habilite o acesso público e anote a URL pública
- Atualize sua configuração de armazenamento:
storage: r2({
binding: "MEDIA",
publicUrl: "https://pub-xxx.r2.dev"
}),
Autenticação Cloudflare Access
Se sua organização usa Cloudflare Access, você pode usá-lo como provedor de autenticação em vez de passkeys, fornecendo login único através do seu provedor de identidade existente. A seguinte configuração o habilita:
emdash({
database: d1({ binding: "DB" }),
storage: r2({ binding: "MEDIA" }),
auth: access({
teamDomain: "myteam.cloudflareaccess.com",
audience: "your-app-audience-tag",
roleMapping: {
"Admins": 50,
"Editors": 40,
},
}),
}),
Consulte o guia de Autenticação para opções de configuração completas.
Variáveis de Ambiente
Recomendado: chave de criptografia
EMDASH_ENCRYPTION_KEY é a chave para criptografar segredos de plugins em repouso (tokens de webhook, chaves Turnstile, etc.). A chave é validada na inicialização; a criptografia de segredos de plugins a usa uma vez habilitada. Defina-a em cada implantação para que os segredos sejam protegidos sem uma mudança de configuração posterior.
A chave é fornecida por você e nunca armazenada no banco de dados; apenas o texto cifrado criptografado é armazenado. Perdê-la significa perder cada segredo criptografado com ela.
Gere uma chave e armazene-a como um segredo Worker com os seguintes comandos:
npx emdash secrets generate
wrangler secret put EMDASH_ENCRYPTION_KEY
Opcional: substituições de valores estáveis
EmDash gera automaticamente o segredo HMAC de visualização e o salt de hash de IP do comentarista e os persiste no banco de dados no primeiro uso. As variáveis de ambiente abaixo são substituições para casos em que você precisa fixar o valor você mesmo — por exemplo, quando um Worker de visualização em um processo separado precisa compartilhar o segredo com seu site principal.
| Variável | Propósito |
|---|---|
EMDASH_PREVIEW_SECRET | Substituição para o segredo HMAC de visualização gerado automaticamente. |
EMDASH_IP_SALT | Substituição para o salt de hash de IP do comentarista gerado automaticamente. |
EMDASH_AUTH_SECRET | Opcional. Se definido, é usado como fonte de salt de IP (a menos que EMDASH_IP_SALT também esteja definido, que tem precedência), mantendo hashes de IP do comentarista estáveis para instalações que já dependem dele. Deixe-o indefinido para uma nova implantação. |
Acesse variáveis de ambiente na sua configuração usando import.meta.env ou o binding env do Cloudflare.
Implantações de Visualização
Implante um branch de visualização:
wrangler deploy --env preview
Adicione uma seção de ambiente ao wrangler.jsonc:
{
"env": {
"preview": {
"d1_databases": [
{
"binding": "DB",
"database_name": "emdash-db-preview",
},
],
},
},
}
Solução de Problemas
”D1 binding not found”
Verifique se o nome do binding em wrangler.jsonc corresponde à sua configuração de banco de dados:
// Must match: d1({ binding: "DB" })
"binding": "DB"
“R2 binding not found”
Verifique se o bucket R2 está corretamente vinculado:
// Must match: r2({ binding: "MEDIA" })
"binding": "MEDIA"
Erros de migração
Se você vir erros de esquema, rastreie os logs do Worker (wrangler tail) e reproduza o erro para capturar a mensagem subjacente — então abra uma issue com essa saída.