TuBrief
구독 채널
비디오
커뮤니티

Cómo distribuir aplicaciones de escritorio creadas por desarrolladores solitarios sin advertencias de seguridad

TuBrief 편집팀
2026년 7월 15일
0
Computing/Software

원본 영상을 바탕으로 AI의 도움을 받아 작성했습니다. 원본 영상이 기준입니다.

Español한국어English中文العربيةहिन्दीDeutschFrançaisPortuguêsРусскийBahasa Indonesia日本語

관련 영상

¿Cuál es la mejor alternativa a Electron? Vamos a descubrirlo.6:33

¿Cuál es la mejor alternativa a Electron? Vamos a descubrirlo.

Better Stack

커뮤니티의 다른 글

사내 시스템에 llm api 붙일 때 마주하는 현실적인 한계와 대응법

2026년 9월 13일

레거시 백엔드에 GPT-6 Astra 붙일 때 예산 승인과 보안 통과를 먼저 끝내는 법이 있습니다

2026년 9월 13일

에이전트끼리 대화하다 6천만 원 청구서가 나오는 이유

2026년 9월 13일

사내 RAG 벡터 검색에 Okta 권한 필터를 직접 거는 방법

2026년 9월 13일

브라우저 에이전트에게 내 구글 계정을 통째로 넘기면 안 되는 이유

2026년 9월 12일

Apple Won the AI Race

2026년 9월 12일

댓글 (0)

Log in to leave a comment

아직 작성된 글이 없습니다

© 2026 . All rights reserved.

TuBrief
구독 채널
비디오
커뮤니티
로그인

Cómo distribuir aplicaciones de escritorio creadas por desarrolladores solitarios sin advertencias de seguridad

Si has terminado una aplicación de escritorio que funciona bien localmente, solo has completado la mitad del desarrollo. El verdadero obstáculo comienza en el momento en que aparece una ventana de advertencia roja, como "archivo dañado" o "Windows protegió su PC", en la pantalla del usuario que acaba de hacer clic en el enlace de descarga.

Superar las barreras de seguridad del sistema operativo, controlar la velocidad de compilación y crear un sistema de actualización automática que se encargue de las versiones más recientes cada vez que el usuario abre la aplicación es más agotador de lo que parece. Incluso si elegiste Tauri v2 por ser más ligero que Electron, los problemas prácticos del proceso de distribución siguen ahí. He resumido cómo los desarrolladores solitarios o los equipos pequeños pueden distribuir sus productos de forma impecable sin desperdiciar tiempo ni dinero innecesario.


1. Utilizar firmas en la nube en lugar de certificados de 700 dólares al año

Una aplicación de escritorio sin firma de código (Code Signing) es tratada como malware a nivel del sistema operativo. Para evitar mostrar advertencias de seguridad en la PC del usuario, se necesita dinero y papeleo.

macOS: Configuración de Apple Developer Account y Entitlements

Para distribuir en macOS, es obligatorio inscribirse en el Apple Developer Program, que cuesta 99 dólares al año. Una vez obtenida la cuenta, debes crear un archivo src-tauri/Entitlements.plist que defina los permisos de excepción de seguridad de memoria para que el webview de Tauri funcione correctamente. Si falta esta configuración, la aplicación se cerrará inmediatamente al iniciarse.

`xml




com.apple.security.cs.allow-jit

com.apple.security.cs.allow-unsigned-executable-memory


`

Especifica este archivo en las opciones de bundle de src-tauri/tauri.conf.json.

`json
{
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Your Name (TEAMID)",
"entitlements": "./Entitlements.plist",
"minimumSystemVersion": "11.0",
"dmg": {
"appPosition": { "x": 180, "y": 170 },
"applicationFolderPosition": { "x": 480, "y": 170 }
}
}
}
}

`

Windows: Ahorrar costos con Azure Trusted Signing

Para pasar el filtro SmartScreen de Windows, anteriormente era necesario obtener un certificado EV (Extended Validation), que costaba entre 400 y 700 dólares al año, en forma de token USB físico. No solo es costoso, sino que es extremadamente engorroso de gestionar para una persona.

La alternativa es Azure Trusted Signing (ATS), el servicio de firma basado en la nube de Microsoft. Si pagas una suscripción mensual de unos 9.99 dólares, Microsoft gestiona la firma dentro de su nube HSM, por lo que no es necesario guardar ninguna llave física.

  1. Crea una cuenta de Azure Trusted Signing y un perfil de certificado en el portal de Azure.
  2. Ingresa la información de suscripción de Azure (AZURE_TENANT_ID, CLIENT_ID, CLIENT_SECRET) y la información de ATS en las variables de entorno (Secrets) de GitHub Actions.
  3. Ejecuta sign-tool durante el proceso de compilación para aplicar la firma digital al archivo MSI o EXE compilado por Tauri.

Una aplicación firmada de esta manera evita las advertencias de Windows SmartScreen desde el momento de la primera descarga, lo que permite retener a los usuarios que, de otro modo, abandonarían en la etapa de instalación.


2. Cómo acelerar la compilación en GitHub Actions en un 90%

Tauri es ligero, pero en el proceso de compilación debe ejecutar el compilador de Rust y las cadenas de herramientas nativas de cada sistema operativo. Aunque funcione bien en tu computadora, es común que ocurran errores de enlace en la computadora de otro miembro del equipo o que la distribución se corrompa debido a la contaminación de dependencias del entorno local. La compilación para distribución debe realizarse obligatoriamente en un pipeline de CI/CD aislado para mayor seguridad.

El problema es que el runner alojado por defecto en GitHub Actions no tiene las especificaciones suficientes para compilar Rust. Si se trata de una estructura que descarga las dependencias y compila desde cero cada vez, es fácil que una compilación de lanzamiento tarde más de 10 minutos.

En este caso, en lugar de usar actions/cache para comprimir y enviar archivos a la nube, la combinación de un plugin de caché dedicado que funciona con almacenamiento NVMe de alto rendimiento (swatinem/rust-cache) o runners alojados dedicados (Namespace, Depot, etc.) cambiará la velocidad drásticamente.

Basado en los registros de compilación del proyecto de código abierto del reproductor de música spotify-player, el resultado de la comparación de rendimiento entre un runner estándar de GitHub y un runner dedicado con caché de volumen local es el siguiente:

Plataforma y configuración de caché Tiempo requerido runner estándar de GitHub Tiempo requerido con optimización de caché Tasa de reducción de tiempo de compilación
Ubuntu Linux 9 min 31 seg 34 seg 94.0% reducción
macOS Darwin 9 min 31 seg 27 seg 95.2% reducción
Windows MSVC 9 min 31 seg 44 seg 92.2% reducción
Costo del flujo de trabajo $0.44 por ejecución $0.074 por ejecución 83.1% ahorro

Simplemente conectando una infraestructura de caché de volumen persistente, el tiempo de espera de compilación del equipo de desarrollo se reduce en al menos un 40%.

La configuración de automatización de distribución se especifica en .github/workflows/publish.yml de la siguiente manera.

`yaml
jobs:
build-binaries:
strategy:
matrix:
platform: [macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
# ... después de los pasos de compilación, llamar a tauri-action

`

Al poner tauri-apps/tauri-action al final del flujo de trabajo, cada vez que envíes una nueva etiqueta (push tag), los instaladores firmados para ambos SO se registrarán automáticamente en GitHub Release Draft.


3. Aislamiento de datos SQLite en preparación para el inicio de sesión webview

Al empaquetar el instalador para Windows, debes decidir el método de instalación del motor de webview, WebView2. Si se garantiza la conexión a Internet y el entorno requiere reducir drásticamente el tamaño del archivo de descarga, el método downloadBootstrapper es ideal, ya que no aumenta el tamaño del paquete. Por el contrario, si te diriges a redes cerradas o entornos sin conexión, es más seguro incluir el offlineInstaller, aunque se añadan unos 127 MB al archivo de instalación.

La forma en que manejas los datos al operar una aplicación basada en Tauri también es importante. Es peligroso simplemente guardar datos en IndexedDB o LocalStorage, que son almacenamiento del navegador.

De hecho, al pasar de Tauri v1 a v2, hubo un cambio interno en el esquema de dominio del webview en el entorno de Windows, de [https://tauri.localhost](https://tauri.localhost) a [http://tauri.localhost](http://tauri.localhost). Debido a esto, hubo muchos casos en los que se perdieron todos los datos existentes debido a que la ruta de la caché del navegador se cambió a la fuerza.

Para evitar el gran desastre de que los datos se inicialicen después de la distribución, la información principal debe almacenarse directamente como un archivo SQLite en el área del sistema de archivos nativo en lugar de en el almacenamiento del webview. Si usas la API appDataDir de Tauri v2, automáticamente encontrará una ruta de sandboxing segura que cumpla con los estándares del sistema operativo.

  • Windows: C:\Users\<UserName>\AppData\Roaming\<BundleIdentifier>
  • macOS: /Users/<UserName>/Library/Application Support/<BundleIdentifier>

Un ejemplo de cómo intervenir en el ciclo de vida de la aplicación dentro del código Rust (src-tauri/src/lib.rs), que es el backend de Tauri v2, para vincular de forma segura la base de datos SQLite al área segura y ejecutar la migración del esquema es el siguiente:

`rust
use std::fs;
use tauri::Manager;
use tauri_plugin_sql::{Migration, MigrationKind};

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
let database_migrations = vec![
Migration {
version: 1,
description: "initialize_user_profiles_table",
sql: "CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL UNIQUE
);",
kind: MigrationKind::Up,
}
];

tauri::Builder::default()
    .setup(|app| {
        let local_app_dir = app.path().app_data_dir()
            .expect("Critical: Could not resolve target operating system app data path.");

        if !local_app_dir.exists() {
            fs::create_dir_all(&local_app_dir)
                .expect("Critical: Failed to establish persistent storage directory structure.");
        }
        
        Ok(())
    })
    .plugin(
        tauri_plugin_sql::Builder::default()
            .add_migrations("sqlite:users.db", database_migrations)
            .build()
    )
    .run(tauri::generate_context!())
    .expect("error while running tauri application");

}

`

Al configurarlo de esta manera, incluso si la caché interna de Electron o Chromium Webview se elimina por completo debido a una actualización automática o reinstalación, la base de datos del usuario real se conservará de forma segura.


4. Construcción de actualizaciones automáticas en segundo plano

El método de inducir a los usuarios a visitar la página de inicio y descargar la nueva versión cada vez aumenta la tasa de abandono. Debes establecer una estructura que sirva los archivos de actualización silenciosamente combinando almacenamiento de objetos en la nube y CDN.

La combinación de Cloudflare R2 y AWS CloudFront es eficiente como servidor de distribución. Cloudflare R2 no tiene tarifas de egreso (Egress Fees), por lo que puedes fijar en cero el costo del tráfico de red generado al publicar archivos de actualización a gran escala.

Política de control de caché de CDN

El archivo de metadatos (latest.json) que el cliente consulta para verificar si hay una nueva versión no debe ser almacenado en caché por la CDN o el navegador. Debes especificar la siguiente política en el encabezado de respuesta:

`http
Cache-Control: no-cache, no-store, must-revalidate

`

Por otro lado, dado que los archivos binarios de instalación reales son inmutables (Immutable) y contienen valores hash únicos, configúralos para que la CDN los mantenga durante el mayor tiempo posible para reducir la carga de tráfico del servidor original.

`http
Cache-Control: public, max-age=31536000, immutable

`

Cambios en la configuración del actualizador de Tauri v2

En Tauri v2, la ubicación de las opciones relacionadas con la actualización se ha movido debajo del bloque plugins.updater. A continuación, la especificación de configuración de tauri.conf.json:

`json
{
"bundle": {
"createUpdaterArtifacts": true
},
"plugins": {
"updater": {
"active": true,
"endpoints": [
"https://cdn.myapp.com/releases/latest.json"
],
"dialog": false,
"pubkey": "dW5zaWduZWQgYm91bmRmaXg...",
"windows": {
"installMode": "passive"
}
}
}
}

`

Para hacer que el usuario actualice sin tener que hacer clic en molestas ventanas de confirmación en el entorno de Windows, debes establecer el installMode en passive o quiet. El modo passive muestra una barra de progreso tranquila en lugar de la ventana del asistente de instalación y luego completa el reemplazo silenciosamente.

Una vez finalizada la configuración, vincula @tauri-apps/plugin-updater y @tauri-apps/plugin-process en el área de frontend para verificar nuevos parches al momento de ejecutar la aplicación e inducir al reinicio.

`typescript
import { check } from "@tauri-apps/plugin-updater";
import { ask } from "@tauri-apps/plugin-dialog";
import { relaunch } from "@tauri-apps/plugin-process";

export async function runBackgroundUpdater(): Promise {
try {
const updatePayload = await check();

if (updatePayload && updatePayload.available) {
  const userResponse = await ask(
    `Una nueva versión [v${updatePayload.version}] está disponible. ¿Desea actualizar y reiniciar la aplicación ahora?`,
    {
      title: "Aviso de actualización automática de software",
      kind: "info",
      okLabel: "Instalar actualización y reiniciar",
      cancelLabel: "Aplicar más tarde"
    }
  );

  if (userResponse) {
    await updatePayload.downloadAndInstall();
    await relaunch();
  }
}

} catch (error) {
console.error("Excepción durante el proceso de verificación de actualización automática:", error);
}
}

`

Simplemente insertando esta función en la fase de montaje inicial del componente de React o Vue de nivel superior, los usuarios siempre usarán el software en su versión más reciente sin necesidad de buscar en la página de inicio ellos mismos.


5. Resumen

  • Reducción de costos: Para un equipo de desarrollo de una sola persona, es más realista aplicar Azure Trusted Signing, que cuesta unos 10 dólares al mes, en lugar de certificados EV que cuestan cientos de dólares cada año, y combinarlo con Cloudflare R2, que no tiene comisiones por tráfico de descarga.
  • Preservación de datos: No es necesario depender del almacenamiento local del navegador, que es propenso a perderse cuando la sesión expira o cambia la especificación del dominio. Debes mantener el archivo de base de datos SQLite bajo la ruta appDataDir controlada por el nativo y ejecutar migraciones de esquema a largo plazo para que los datos no se corrompan durante las actualizaciones de la aplicación.
  • Velocidad de distribución: No compiles en tu propia computadora para subirlo manualmente; debes configurar una matriz de compilación (build matrix) a la que se le apliquen técnicas de caché de runner para automatizar la versión de lanzamiento y evitar estrés en la etapa de creación del paquete.