SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor · Actualizado 2026-10-28

Cómo alojar Actual Budget en tu propio VPS

Aloja Actual Budget con Docker Compose en un VPS: conserva el volumen de datos, configura HTTPS para el navegador, crea tu primer presupuesto, importa bancos y haz copias.

Qué va a crear

Actual Budget es una aplicación de presupuesto por sobres autoalojada. Es la opción habitual para quienes buscan una alternativa a YNAB que puedan alojar por su cuenta. El servidor consta de un contenedor, un volumen de datos y un nombre HTTPS. Todas las funciones habituales de un presupuesto funcionan sin problemas en el VPS más pequeño que pueda alquilar, porque el servidor principalmente almacena archivos y los sincroniza.

Conviene entender la arquitectura antes de escribir cualquier comando. El presupuesto es una base de datos SQLite que reside en el navegador y en cada aplicación móvil. El servidor que va a instalar es un endpoint de sincronización: almacena la lista de cuentas, los archivos del presupuesto y el registro de cambios que permite que el teléfono y el portátil coincidan. Por eso la aplicación sigue funcionando cuando el servidor está caído. También por eso perder el servidor no implica perder el presupuesto, siempre que un cliente conserve una copia.

Por qué el servidor necesita HTTPS

Actual requiere HTTPS, y no es una formalidad. Actual necesita una función del navegador llamada SharedArrayBuffer para funcionar, y los navegadores sólo la habilitan cuando la página está aislada de otros orígenes dentro de lo que la especificación denomina un contexto seguro. Un contexto seguro es https:// o http://localhost. Cargue la aplicación desde http://203.0.113.10:5006 en un navegador de otro equipo y el navegador nunca entrega esa función a la página, por lo que el presupuesto no se carga. Los teléfonos no tienen ninguna excepción. Las FAQ de Actual indican que una aplicación oficial para iOS está en fase beta y se conecta a su propio servidor, y que todavía no existe una aplicación oficial para Android. Por tanto, en la mayoría de los teléfonos se usa la misma aplicación web, instalada en la pantalla de inicio como una Progressive Web App, y se aplica la misma regla del contexto seguro.

Hay dos configuraciones viables. Coloque un certificado válido para un nombre de dominio real delante del contenedor, que es lo que hace esta guía. O proporcione al servidor un certificado autofirmado con ACTUAL_HTTPS_KEY y ACTUAL_HTTPS_CERT, como documenta el proyecto, y acepte una advertencia del navegador en cada dispositivo. Un certificado gratuito de Let's Encrypt se obtiene en cinco minutos, así que elija la primera opción.

Instalar Actual Budget con Docker Compose

Instale Docker primero si el servidor es nuevo. Si la sintaxis de los archivos de Compose es nueva para usted, la guía conceptos básicos de Docker Compose para un VPS explica los campos que se usan a continuación.

sudo install -d -m 755 /opt/actual
sudo install -d -m 700 /opt/actual/data

Escriba /opt/actual/docker-compose.yml:

services:
  actual:
    image: actualbudget/actual-server:latest
    container_name: actual
    restart: unless-stopped
    ports:
      - '127.0.0.1:5006:5006'
    volumes:
      - ./data:/data

Hay tres detalles importantes en ese archivo.

La imagen es actualbudget/actual-server:latest, publicada por el proyecto en Docker Hub y replicada en ghcr.io/actualbudget/actual. Existe una etiqueta latest-alpine para máquinas de baja potencia.

El contenedor escribe todo en /data. Dentro encontrará server-files, que contiene account.sqlite con sus tokens de inicio de sesión y de sesión, y user-files, que contiene los propios archivos del presupuesto. Monte esa ruta o el siguiente docker compose pull eliminará su presupuesto. ACTUAL_DATA_DIR puede moverlo, pero el valor predeterminado es adecuado.

El puerto se publica sólo en 127.0.0.1. Un 5006:5006 sin dirección publica el puerto en todas las interfaces, y Docker escribe sus propias reglas antes que ufw, por lo que la aplicación quedaría expuesta a Internet incluso con un firewall que deniegue todo. Esta particularidad se explica en por qué los puertos publicados por Docker eluden ufw. Enlazarlo con loopback significa que sólo el reverse proxy del mismo servidor puede acceder a él.

Inícielo:

cd /opt/actual
docker compose up --detach
docker compose logs -f actual

El registro se estabiliza cuando el servidor informa de que está escuchando en el puerto 5006. Compruébelo localmente antes de modificar el DNS:

curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:5006/

Un 200 significa que la aplicación está atendiendo peticiones. curl: (7) Failed to connect significa que ningún proceso aceptó la conexión en 127.0.0.1:5006. Ejecute docker compose ps --all, porque un docker compose ps sin opciones sólo muestra los contenedores en ejecución. Si el contenedor aparece como detenido, la causa habitual es un problema de permisos en el volumen montado, visible como una línea EACCES en el registro.

Configura un certificado y un nombre real

Apunta un registro A al VPS, budget.example.com, y espera a que resuelva. Después, instala nginx y emite el certificado. La guía Certbot en Ubuntu 24.04 con nginx explica completamente la emisión y el temporizador de renovación.

El bloque del proxy:

server {
    listen 443 ssl;
    http2 on;
    server_name budget.example.com;

    ssl_certificate     /etc/letsencrypt/live/budget.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/budget.example.com/privkey.pem;

    client_max_body_size 100m;

    location / {
        proxy_pass http://127.0.0.1:5006;
        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;
    }
}

client_max_body_size es la línea que se suele olvidar. La sincronización diaria sólo envía tus cambios, pero el archivo de presupuesto completo se carga cuando registras un presupuesto por primera vez en el servidor y cada vez que reinicias la sincronización. nginx establece por defecto un cuerpo de solicitud de 1 MB, así que cuando el archivo supera ese tamaño, esas cargas completas fallan con 413 Request Entity Too Large en el registro de acceso de nginx, mientras la aplicación sólo muestra un error de sincronización genérico. El servidor tiene sus propios límites independientes: ACTUAL_UPLOAD_FILE_SYNC_SIZE_LIMIT_MB está establecido en 20 de forma predeterminada y ACTUAL_UPLOAD_SYNC_ENCRYPTED_FILE_SYNC_SIZE_LIMIT_MB en 50, así que configura el límite de nginx por encima del que corresponda en tu caso.

Recarga y prueba:

sudo nginx -t && sudo systemctl reload nginx
curl -fsS -o /dev/null -w '%{http_code}\n' https://budget.example.com/

Primer inicio: la contraseña y el primer archivo de presupuesto

Abra https://budget.example.com en un navegador. La primera pantalla le pide que establezca una contraseña para el servidor. Esa contraseña protege todo el servidor, así que genere una contraseña larga y aleatoria y guárdela en un lugar que pueda volver a encontrar, como un gestor de contraseñas Vaultwarden autoalojado. De forma predeterminada no hay cuentas de usuario que crear: el servidor tiene una sola contraseña, por lo que compartir un presupuesto implica compartir esa contraseña. Los inicios de sesión independientes sólo son posibles si conecta un proveedor OpenID, que Actual admite para configuraciones multiusuario.

A continuación, cree un archivo de presupuesto. Actual le pregunta si quiere activar el cifrado de extremo a extremo. Responda que sí. El servidor almacenará únicamente texto cifrado, que es la opción adecuada para datos financieros en una máquina alquilada. El coste es real: la contraseña de cifrado nunca llega al servidor, así que si la pierde, el archivo desaparece y no existe ningún mecanismo de restablecimiento. Anótela antes de continuar en esa pantalla.

Establezca los saldos iniciales a partir de las cifras actuales de su banco, en lugar de importar años de historial. La elaboración de presupuestos por sobres parte del dinero que tiene ahora, así que no tener historial no le supone ningún coste.

Importar movimientos

Aquí la honestidad importa más que el entusiasmo, porque la importación es el principal motivo por el que la gente abandona las herramientas de presupuestación autoalojadas.

La introducción manual es la base y siempre funciona. En un método de sobres, podría decirse que ese es precisamente el objetivo, porque introducir una compra obliga a prestarle atención.

La importación de archivos gestiona la mayor parte del trabajo. Actual lee CSV, QIF, OFX, QFX y CAMT, y todos los bancos exportan al menos uno de esos formatos. Importe cada cuenta desde la pantalla de la cuenta y asigne las columnas cuando el archivo sea un CSV.

Existe la sincronización automática con bancos, pero necesita un servicio de terceros porque el servidor no puede comunicarse con los bancos por sí solo. Actual admite SimpleFIN Bridge para bancos de Norteamérica, Enable Banking para Europa, Akahu para Nueva Zelanda y Pluggy.ai para Brasil. GoCardless todavía es compatible, pero no acepta cuentas nuevas. Debe registrarse directamente con el proveedor, generar las credenciales y añadirlas al servidor. SimpleFIN Bridge cobra 15 dólares estadounidenses al año más impuestos por hasta 25 instituciones a fecha de octubre de 2026. Los demás servicios tienen precios diferentes.

Hay dos limitaciones que debe aceptar antes de depender de esta función. Las credenciales de la API se almacenan en el servidor y no están protegidas por cifrado de extremo a extremo, porque el servidor tiene que utilizarlas. Además, no se sincroniza nada mientras Actual está cerrado: la sincronización automática está desactivada de forma predeterminada y, cuando se activa, sólo se ejecuta mientras la aplicación está abierta. Por tanto, el servidor nunca consulta los bancos por su cuenta.

Copias de seguridad: solo son archivos

Todo lo que le importa está en /opt/actual/data. No hay ningún paso de exportación ni ningún volcado de base de datos que automatizar con un script.

La única trampa es SQLite. Copiar account.sqlite mientras el servidor escribe en él puede capturar una transacción incompleta, y no lo descubrirá hasta que intente restaurarla. Detenga el contenedor durante los pocos segundos que tarda la copia:

cd /opt/actual
docker compose stop
restic -r sftp:backup@backup.example.com:/srv/restic backup /opt/actual/data
docker compose start

Programe esta tarea con el método de copias de seguridad de restic en un VPS, que cubre la configuración del repositorio, la retención y el simulacro de restauración. Ejecute el simulacro de restauración. Una copia de seguridad que nunca ha restaurado es solo una suposición.

Las copias de seguridad automáticas del propio Actual son independientes y conviene conocerlas, pero solo existen en la aplicación de escritorio. Conserva hasta 10 copias recientes del archivo de presupuesto, disponibles en File > Load Backup, lo que permite resolver el caso de «he eliminado una categoría por error» sin tocar el servidor. La aplicación web en un navegador no conserva copias de este tipo. Por tanto, si todos los miembros de la casa usan el navegador, la copia de seguridad del servidor anterior es la única que tiene.

Actualización del servidor

cd /opt/actual
docker compose pull
docker compose up --detach

Compose recrea el contenedor a partir de la nueva imagen y vuelve a asociar el mismo volumen, por lo que los datos se conservan. Actualice también los clientes. Un cliente más antiguo que los datos que recibe deja de aplicar cambios y muestra el mensaje Update Required. Haga una copia de seguridad antes de saltar a una versión principal, porque las migraciones se ejecutan durante el primer arranque y no existe una ruta de downgrade. Actual tolera un tag flotante latest porque su estado es un directorio de archivos, pero no ocurre lo mismo con una aplicación que usa una base de datos real; autoalojar Chatwoot explica los tags fijados y el volcado previo a la actualización que requiere esta práctica.

Qué falla y qué verá

La aplicación carga, pero la sincronización nunca termina. Compruebe el registro de acceso de nginx para 413. Ese es client_max_body_size configurado con un valor demasiado bajo. Un 502 indica que nginx no recibió una respuesta utilizable del upstream. Lo más habitual es que el contenedor esté detenido o no escuche en 5006, así que compruebe docker compose ps --all y el registro del contenedor antes de hacer cualquier otra cosa.

La aplicación no carga en otro dispositivo o indica que falta SharedArrayBuffer. La página no está en un contexto seguro. La barra de direcciones mostrará http:// con una dirección IP o un nombre de host que no es localhost. Corrija el certificado en lugar de buscar una solución alternativa.

Aparece un mensaje que indica que el archivo de presupuesto no es compatible con esta versión. El archivo se abrió con una versión de Actual más reciente que la del cliente que usa ahora. Actualice el cliente al menos a esa versión o restaure una copia de seguridad creada antes de que la versión más reciente modificara el archivo y vuelva a cargarlo.

El contenedor se reinicia continuamente. Lea docker compose logs actual. Un error de permisos en /data indica que el usuario del contenedor no puede escribir en el directorio montado. Un error de dirección en uso indica que otro proceso ya ocupa 5006 en loopback.

La primera carga parece lenta. El archivo de presupuesto completo se descarga en el navegador al abrirlo. Es una transferencia grande seguida de lecturas locales. No es un problema de dimensionamiento del servidor, y añadir RAM no cambiará el comportamiento.

FAQ

¿Actual Budget necesita HTTPS para funcionar?

Sí, en la práctica. Actual necesita la función SharedArrayBuffer del navegador para ejecutarse, y los navegadores sólo la habilitan en un contexto seguro, es decir, https:// o http://localhost. A través de HTTP sin cifrar desde otra máquina, la aplicación no se cargará. Hay una aplicación oficial para iOS en fase beta y todavía no existe una aplicación oficial para Android, por lo que la mayoría de los teléfonos usan la misma aplicación web y están sujetos a la misma regla. (FAQ) Use un certificado de Let's Encrypt en un nombre de host real, o un certificado autofirmado con ACTUAL_HTTPS_KEY y ACTUAL_HTTPS_CERT si puede aceptar una advertencia de certificado en cada dispositivo.

¿Actual puede importar automáticamente las transacciones de mi banco?

Sólo mediante un servicio de terceros en el que usted se registre: SimpleFIN Bridge en Norteamérica, Enable Banking en Europa, Akahu en Nueva Zelanda o Pluggy.ai en Brasil. GoCardless es compatible, pero no acepta cuentas nuevas. Esas credenciales de API se almacenan en su servidor y no están cubiertas por el cifrado de extremo a extremo. La sincronización automática está desactivada de forma predeterminada y, una vez activada, sólo se ejecuta mientras Actual está abierto, por lo que el servidor no consulta nada en segundo plano. La importación de CSV, QIF, OFX, QFX y CAMT no necesita ningún tercero.

¿Qué tengo que respaldar exactamente?

El directorio de datos montado, que es /opt/actual/data en esta guía. Contiene server-files/account.sqlite, con los inicios de sesión y las sesiones, y user-files, con los archivos de presupuesto. Detenga el contenedor antes de copiarlo, porque copiar una base de datos SQLite activa puede capturar una escritura parcial. Ningún otro elemento del servidor contiene estado.

¿Qué ocurre si pierdo la contraseña de cifrado?

El archivo no se puede recuperar. La contraseña nunca llega al servidor, que es precisamente el objetivo del cifrado de extremo a extremo, por lo que no existe ninguna opción de restablecimiento ni vía de soporte. Guárdela en un gestor de contraseñas en cuanto cree el archivo y conserve una copia en un lugar que no dependa de este mismo servidor.

¿Cuánto servidor necesita Actual Budget?

Muy poco. El contenedor sirve recursos y archivos estáticos, y los cálculos del presupuesto se realizan en el navegador. Una vCPU compartida con 1 GB de RAM lo ejecuta sin problemas, y el directorio de datos de un presupuesto doméstico con varios años de historial se mantiene en decenas de megabytes. La presión sobre el disco procede de sus copias de seguridad y de los demás contenedores, no de Actual. Si está dimensionando un equipo que también debe ejecutar algo más exigente, normalmente un servidor de fotos es el que fija el mínimo, así que consulte cuánta RAM necesitan realmente PhotoPrism e Immich antes de elegir un plan. La misma lógica se aplica a una pila multimedia: la transcodificación determina el plan, mientras que un frontend de navegador como Halcyon, que convierte una biblioteca de Jellyfin en un videoclub de los años 90 que se puede recorrer consume aproximadamente lo mismo que Actual.

¿Te resultó útil este artículo?