Maybe: Self-Hosted Personal Finance
Maybe is an open-source personal finance application for managing accounts, transactions, budgets, investments, and household financial views. Maybe is a typical Rails web application: it stores business data in PostgreSQL in production and uses Redis for background job queues.
Pigsty provides the app/maybe template, which connects the stateless Maybe Web / Worker containers to PostgreSQL managed by Pigsty and uses local Redis for the Sidekiq queue. This keeps your most important financial data in a PostgreSQL cluster that can be backed up, monitored, and recovered, rather than in an ephemeral Docker data volume.
The upstream Maybe repository has been archived, and its latest release is
v0.6.0. GHCR currently publishesstableandlatestimage tags. Pigsty usesstableby default, which tracks the latest release image.
Quick Start
Run the following on a fresh Linux x86 / ARM server with a compatible operating system:
curl -fsSL https://repo.pigsty.io/get | bash; cd ~/pigsty
./bootstrap # Install Pigsty dependencies
./configure -c app/maybe # Use the Maybe configuration template
vi pigsty.yml # Required: SECRET_KEY_BASE, database password, domain
./deploy.yml # Install Pigsty, Infra, Etcd, and PostgreSQL
./docker.yml # Install Docker and Compose
./app.yml # Install Maybe
Maybe listens on port 5002 by default. After installation, you can access it at:
http://<your_ip_address>:5002http://maybe.pigsty
On your first visit, select the option to create an account on the login page, then register your first household account to get started.
To access Maybe through maybe.pigsty, add the following entry to /etc/hosts on the machine running your browser:
10.10.10.10 maybe.pigsty
To expose the service to the public internet, use a real domain and HTTPS certificate, and modify infra_portal as described below.
Checklist
- Prepare a fresh Linux server with at least
2C4G; use an SSD/NVMe disk. - Confirm that the server has a static private IPv4 address and can access GHCR / Docker Hub, or that a registry mirror is configured.
- After running
./configure -c app/maybe, change the default passwords, domain, and secrets inpigsty.yml. - Generate a new
SECRET_KEY_BASEwithopenssl rand -hex 64. - Keep
POSTGRES_PASSWORDconsistent with the password of themaybeuser inpg_users. - For public access, configure a real domain, an HTTPS certificate, and firewall access rules.
- Confirm that PostgreSQL backup jobs run correctly, and check
pig pb infoafter deployment.
Configuration Template
conf/app/maybe.yml defines a single-node, self-hosted Maybe template. The default topology includes:
maybe: The node running the Maybe Web / Worker / Redis containers.pg-maybe: The PostgreSQL database cluster managed by Pigsty.infra: Infrastructure services such as Nginx ingress, Grafana, and VictoriaMetrics.etcd: The distributed configuration store required by Patroni.
Key configuration excerpts:
maybe:
hosts: { 10.10.10.10: {} }
vars:
app: maybe
apps:
maybe:
file:
- { path: /data/maybe ,state: directory ,mode: 0755 }
- { path: /data/maybe/storage ,state: directory ,owner: 1000 ,group: 1000 ,mode: 0755 }
- { path: /data/maybe/redis ,state: directory ,mode: 0755 }
conf:
MAYBE_IMAGE: ghcr.io/maybe-finance/maybe
MAYBE_VERSION: stable
MAYBE_PORT: 5002
MAYBE_DATA: /data/maybe
APP_DOMAIN: maybe.pigsty
SECRET_KEY_BASE: 2f1e4c3d5b6a79808796a5b4c3d2e1f00123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567
DB_HOST: 10.10.10.10
DB_PORT: 5432
POSTGRES_USER: maybe
POSTGRES_PASSWORD: MaybeFinance2026
POSTGRES_DB: maybe_production
REDIS_VERSION: 7-alpine
pg-maybe:
hosts: { 10.10.10.10: { pg_seq: 1, pg_role: primary } }
vars:
pg_cluster: pg-maybe
pg_users:
- { name: maybe ,password: MaybeFinance2026 ,pgbouncer: true ,roles: [ dbrole_admin ] ,comment: admin user for maybe service }
pg_databases:
- { name: maybe_production ,owner: maybe ,revokeconn: true ,comment: maybe main database }
pg_hba_rules:
- { user: maybe ,db: maybe_production ,addr: 172.16.0.0/12 ,auth: pwd ,title: 'allow maybe access from local docker network' }
pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]
Here, maybe_production is the default production database name used upstream by Maybe / Rails. You can rename it to maybe, but you must update POSTGRES_DB, pg_databases.name, pg_hba_rules.db, and every reference in documentation and operational scripts at the same time.
Important Parameters
app.yml copies the app/maybe directory to /opt/maybe and uses apps.maybe.conf to override /opt/maybe/.env. Common parameters include:
| Parameter | Default | Description |
|---|---|---|
MAYBE_IMAGE | ghcr.io/maybe-finance/maybe | Maybe image repository |
MAYBE_VERSION | stable | Image tag; keep stable for production |
MAYBE_PORT | 5002 | Host port exposed by Maybe |
MAYBE_DATA | /data/maybe | Persistent directory on the host |
APP_DOMAIN | maybe.pigsty | Placeholder for the default Maybe ingress domain |
SECRET_KEY_BASE | Sample random string | Rails encryption and signing secret; must be replaced in production |
DB_HOST / DB_PORT | 10.10.10.10 / 5432 | Pigsty PostgreSQL endpoint |
POSTGRES_USER | maybe | Application user that connects Maybe to PostgreSQL |
POSTGRES_PASSWORD | MaybeFinance2026 | Application user password; must be replaced in production |
POSTGRES_DB | maybe_production | Maybe production database |
REDIS_VERSION | 7-alpine | Local Redis image tag |
Generate a production secret with:
openssl rand -hex 64
When changing the password, keep the application and database definitions synchronized. For example:
apps:
maybe:
conf:
POSTGRES_PASSWORD: <new-password>
pg_users:
- { name: maybe ,password: <new-password> ,pgbouncer: true ,roles: [ dbrole_admin ] }
Domain and Ingress
The template adds a Maybe entry to infra_portal by default:
infra_portal:
home : { domain: i.pigsty }
maybe:
domain: maybe.pigsty
endpoint: "10.10.10.10:5002"
websocket: true
To use a real domain such as finance.example.com, replace the placeholder in bulk:
sed -ie 's/maybe.pigsty/finance.example.com/g' pigsty.yml
Then apply the Nginx ingress configuration:
./infra.yml -t nginx
To request an HTTPS certificate, first ensure that the domain resolves to the current node, then add certbot under infra_portal.maybe:
maybe:
domain: finance.example.com
endpoint: "10.10.10.10:5002"
websocket: true
certbot: finance.example.com
Then run:
make cert
./infra.yml -t nginx
Operations
Maybe is installed in /opt/maybe. Common commands include:
cd /opt/maybe
make up # Start Maybe
make run # Start in the foreground and show logs
make restart # Restart containers
make down # Stop containers
make status # Show container status
make log # Follow logs
make health # Check the Rails /up health endpoint
make migrate # Run Rails db:prepare manually
make console # Enter the Rails console
make exec # Enter a shell in the maybe-web container
The web container automatically runs db:prepare at startup, so manual migration is not usually required. If the startup logs report a database migration problem after an image upgrade, inspect the logs, then run:
cd /opt/maybe
make pull
make up
make log
Data and Backup
Maybe state is divided into two categories:
- Business data is stored in the Pigsty PostgreSQL database
maybe_production. - Attachments and cache are stored in the host directories
/data/maybe/storageand/data/maybe/redis.
By default, the template schedules a full PostgreSQL backup every day at 1:00 AM:
pg_crontab: [ '00 01 * * * /pg/bin/pg-backup full' ]
After deployment, check the backup status:
pig pb info
If you use Maybe to store real financial data in production, at minimum:
- Regularly verify that PostgreSQL backups succeed.
- Place the pgBackRest repository on reliable storage or object storage.
- Include
/data/maybe/storagein file-level backups; for example, use restic to back it up to S3. - Do not expose
SECRET_KEY_BASE, database passwords, or API keys in a public repository.
Security Recommendations
Maybe manages highly sensitive personal and household financial data. For production use:
- Change all Pigsty default passwords, especially
pg_admin_password,pg_monitor_password,patroni_password, andhaproxy_admin_password. - Change the Maybe database user password in
POSTGRES_PASSWORD. - Use a new
SECRET_KEY_BASE; do not retain the sample value from the template. - Enable HTTPS for public access and restrict access to administration ports.
- If you enable
OPENAI_ACCESS_TOKENorSYNTH_API_KEY, assess both external API costs and the boundary of data exposure.
The upstream Maybe repository has been archived. It is suitable for users who are satisfied with the existing feature set and prefer long-term local ownership. If you need continuously evolving features or automatic bank synchronization, evaluate the upstream maintenance status before adopting it.
References
- Maybe project: https://github.com/maybe-finance/maybe
- Maybe Docker self-hosting guide: https://github.com/maybe-finance/maybe/blob/main/docs/hosting/docker.md
- Pigsty Maybe template: https://github.com/pgsty/pigsty/blob/main/conf/app/maybe.yml
- Pigsty Docker module
- Pigsty Nginx ingress
Feedback
Was this page helpful?
Thanks for the feedback! Please let us know how we can improve.
Sorry to hear that. Please let us know how we can improve.