
Distribuindo apps desktop: assinatura e instaladores
Você passou meses construindo um app desktop. O código está sólido, os testes passam, a UX ficou boa. Então você gera o instalador e manda para o cliente testar. Ele tenta abrir o arquivo e recebe: "O Windows Defender SmartScreen impediu a inicialização de um aplicativo não reconhecido." Ou, no macOS: "Não é possível abrir 'SeuApp.app' porque o desenvolvedor não pode ser verificado."
Esse momento é evitável. Code signing — assinatura digital do código — é o que diferencia um app que instala sem alarmes de um app que parece malware para os sistemas operacionais modernos. Não é um detalhe de distribuição que pode ser deixado para depois. É um requisito para qualquer app que vai ser instalado por usuários reais fora do seu ambiente de desenvolvimento.
O processo é diferente em cada plataforma e tem custos e prazos envolvidos. Entender como funciona antes de chegar na fase de distribuição poupa semanas de atraso e surpresas desagradáveis com clientes.
Windows: Certificado EV e Authenticode
O Windows usa o padrão Authenticode para verificação de código assinado. O SmartScreen, sistema de reputação da Microsoft, analisa dois fatores: se o código está assinado, e qual a reputação acumulada do certificado usado.
Existem dois tipos de certificados para Windows:
Certificado OV (Organization Validation): Verifica que a organização existe, mas o SmartScreen ainda vai mostrar aviso de "editor desconhecido" nas primeiras instalações até que o certificado acumule reputação suficiente. Para apps com poucos usuários, isso pode levar meses.
Certificado EV (Extended Validation): Requer verificação presencial ou notarial da identidade do titular, custa mais (tipicamente US$ 300 a 500/ano), mas bypassa o processo de acumulação de reputação do SmartScreen imediatamente. Para apps corporativos, o EV é o caminho correto.
Fornecedores como DigiCert, Sectigo e GlobalSign emitem certificados EV. O processo de validação leva de alguns dias a duas semanas dependendo do fornecedor e da rapidez de resposta à documentação solicitada.
Com electron-builder, a configuração de signing no Windows é:
{
"build": {
"win": {
"target": ["nsis", "portable"],
"certificateFile": "cert.pfx",
"certificatePassword": "${CERTIFICATE_PASSWORD}",
"signingHashAlgorithms": ["sha256"],
"signDlls": true
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true,
"shortcutName": "SeuApp"
}
}
}
O signDlls: true é importante: sem ele, apenas o executável principal é assinado, e DLLs não assinadas dentro do instalador podem disparar alertas do antivírus.
A senha do certificado nunca deve estar no código ou no repositório. Deve ser uma variável de ambiente injetada pelo CI/CD — GitHub Actions Secrets, GitLab CI Variables ou equivalente.
macOS: Developer ID e Notarization pela Apple
O macOS tem um processo em dois estágios: signing com um certificado Developer ID, e notarization — submissão do app assinado para análise automatizada da Apple antes da distribuição.
O Gatekeeper, sistema de segurança do macOS, desde o Catalina (2019) exige notarization para qualquer app distribuído fora da Mac App Store. Sem notarization, o macOS bloqueia a abertura do app com a mensagem de "desenvolvedor não verificado".
O Developer ID requer uma conta no Apple Developer Program (US$ 99/ano). O certificado é gerado via Xcode ou Keychain Access e exportado como arquivo .p12 para uso em ambientes de CI.
A configuração no electron-builder para macOS:
{
"build": {
"mac": {
"target": ["dmg", "zip"],
"category": "public.app-category.productivity",
"identity": "Developer ID Application: Sua Empresa (TEAM_ID)",
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "entitlements.mac.plist",
"entitlementsInherit": "entitlements.mac.plist",
"notarize": {
"teamId": "TEAM_ID"
}
}
}
}
O hardenedRuntime: true é obrigatório para notarization. O arquivo entitlements.mac.plist declara as permissões que o app precisa — acesso à rede, câmera, microfone, etc. A Apple analisa se as permissões declaradas fazem sentido para o tipo de app.
O processo de notarization leva de alguns minutos a algumas horas. Em um pipeline de CI, isso significa que o build de release pode demorar mais do que builds de desenvolvimento. Planeje isso no SLA de deploy.
Linux: AppImage, .deb e Snap
Linux é mais permissivo que Windows e macOS em termos de verificação de código — não há um sistema centralizado equivalente ao SmartScreen ou ao Gatekeeper. Mas a escolha do formato de distribuição impacta diretamente a experiência de instalação.
| Formato | Prós | Contras | Indicado para |
|---|---|---|---|
| AppImage | Portável, sem instalação | Sem auto-update nativo | Distribuição avulsa |
| .deb | Integração com apt, familiar | Só Debian/Ubuntu | Ambientes controlados |
| .rpm | Integração com dnf/yum | Só Red Hat/Fedora | Ambientes RHEL corporativos |
| Snap | Distribuição universal, sandboxed | Inicialização mais lenta | Distribuição pública |
| Flatpak | Sandbox forte, universal | Setup inicial complexo | Apps para usuário final |
Para distribuição corporativa — onde a empresa controla as máquinas dos funcionários — o .deb ou .rpm é a escolha mais prática porque permite automatizar a instalação via ferramentas de gestão de configuração como Ansible ou scripts de provisionamento.
Para distribuição pública ampla, o AppImage tem a vantagem de rodar em praticamente qualquer distribuição Linux sem instalação. O Snap e o Flatpak são alternativas com distribuição via lojas (Snap Store, Flathub) mas adicionam complexidade ao processo de publicação.
CI/CD para Builds Multi-plataforma
Builds para Windows, macOS e Linux em paralelo são viáveis com GitHub Actions usando runners específicos por plataforma:
# .github/workflows/release.yml
name: Release Build
on:
push:
tags:
- 'v*'
jobs:
build:
strategy:
matrix:
os: [windows-latest, macos-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Build and Sign (Windows)
if: matrix.os == 'windows-latest'
env:
CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERT_PASSWORD }}
CSC_LINK: ${{ secrets.WINDOWS_CERT_BASE64 }}
run: npm run build:win
- name: Build and Notarize (macOS)
if: matrix.os == 'macos-latest'
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
CSC_LINK: ${{ secrets.MACOS_CERT_BASE64 }}
CSC_KEY_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }}
run: npm run build:mac
- name: Build (Linux)
if: matrix.os == 'ubuntu-latest'
run: npm run build:linux
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: build-${{ matrix.os }}
path: dist/
O certificado .p12 é armazenado como base64 em um GitHub Secret (CSC_LINK), não como arquivo no repositório. O electron-builder decodifica automaticamente quando encontra o valor em base64.
Conclusão com CTA
Code signing e notarization são investimentos que a maioria dos projetos descobre que deveria ter feito desde o início quando chega na primeira demonstração para cliente e o Windows bloqueia o instalador. O processo tem custos — entre US$ 100 e US$ 500/ano dependendo das plataformas — e prazos de validação que precisam entrar no cronograma do projeto.
A parte boa é que, com a configuração de CI/CD correta, o processo se torna completamente automatizado depois do setup inicial. Cada release gera instaladores assinados e notarizados para todas as plataformas de forma transparente.
Na SystemForge, o pipeline de build e distribuição — incluindo code signing para todas as plataformas relevantes — é parte do entregável de qualquer projeto de app desktop. Se você está planejando distribuir um app desktop para clientes e quer estruturar o processo de distribuição de forma profissional desde o início, podemos ajudar.
Precisa de Software Desktop?
Desenvolvemos aplicativos desktop multiplataforma com Electron ou Tauri.
Saiba mais →Precisa de ajuda?

