Yuvomi
Stack
Self-hosted family planner: tasks, shared calendar with CalDAV/CardDAV, shopping, meals, budget, notes, contacts and health in one installable PWA on a single SQLite database. Source: https://github.com/ulsklyc/yuvomi
Image details
Source details
Configuration
TypeComposelinuxghcr.io/ulsklyc/yuvomi:latest${OIKOS_HTTP_PORT:-3000}:3000/data : oikos_data/backups : oikos_backups/app/modules : oikos_modulesNODE_ENV=productionPORT=3000DB_PATH=/data/yuvomi.dbBACKUP_DIR=/backupsMODULES_ALLOW_WEB_INSTALL=${MODULES_ALLOW_WEB_INSTALL:-false}SESSION_SECRET=${SESSION_SECRET:?Set SESSION_SECRET in .env}DB_ENCRYPTION_KEY=${DB_ENCRYPTION_KEY:?Set DB_ENCRYPTION_KEY in .env}SESSION_SECURE=${SESSION_SECURE:-false}TRUST_PROXY=${TRUST_PROXY:-1}BASE_URL=${BASE_URL:-}TZ=${TZ:-UTC}WEATHER_LAT=${WEATHER_LAT:-}WEATHER_LON=${WEATHER_LON:-}WEATHER_CITY=${WEATHER_CITY:-}WEATHER_UNITS=${WEATHER_UNITS:-metric}OPENWEATHER_API_KEY=${OPENWEATHER_API_KEY:-}OPENWEATHER_CITY=${OPENWEATHER_CITY:-Berlin}OPENWEATHER_UNITS=${OPENWEATHER_UNITS:-metric}OPENWEATHER_LANG=${OPENWEATHER_LANG:-en}EMAIL_SMTP_HOST=${EMAIL_SMTP_HOST:-}EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-}EMAIL_SMTP_SECURE=${EMAIL_SMTP_SECURE:-}EMAIL_SMTP_USER=${EMAIL_SMTP_USER:-}EMAIL_SMTP_PASS=${EMAIL_SMTP_PASS:-}EMAIL_FROM_ADDRESS=${EMAIL_FROM_ADDRESS:-}EMAIL_FROM_NAME=${EMAIL_FROM_NAME:-}VAPID_SUBJECT=${VAPID_SUBJECT:-}OIDC_ISSUER=${OIDC_ISSUER:-}OIDC_CLIENT_ID=${OIDC_CLIENT_ID:-}OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET:-}OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI:-}OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM=${OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM:-false}OIDC_TOKEN_AUTH_METHOD=${OIDC_TOKEN_AUTH_METHOD:-}OIDC_ALLOW_SIGNUP=${OIDC_ALLOW_SIGNUP:-true}AUTH_ALLOW_PASSWORD_LOGIN=${AUTH_ALLOW_PASSWORD_LOGIN:-true}BACKUP_ENABLED=${BACKUP_ENABLED:-true}BACKUP_SCHEDULE=${BACKUP_SCHEDULE:-0 2 * * *}BACKUP_KEEP=${BACKUP_KEEP:-7}WEBDAV_BACKUP_ENABLED=${WEBDAV_BACKUP_ENABLED:-}WEBDAV_BACKUP_URL=${WEBDAV_BACKUP_URL:-}WEBDAV_BACKUP_USERNAME=${WEBDAV_BACKUP_USERNAME:-}WEBDAV_BACKUP_PASSWORD=${WEBDAV_BACKUP_PASSWORD:-}WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-}WEBDAV_BACKUP_KEEP=${WEBDAV_BACKUP_KEEP:-}FIXER_API_KEY=${FIXER_API_KEY:-}GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}GOOGLE_REDIRECT_URI=${GOOGLE_REDIRECT_URI:-}GOOGLE_DRIVE_CLIENT_ID=${GOOGLE_DRIVE_CLIENT_ID:-}GOOGLE_DRIVE_CLIENT_SECRET=${GOOGLE_DRIVE_CLIENT_SECRET:-}GOOGLE_DRIVE_REDIRECT_URI=${GOOGLE_DRIVE_REDIRECT_URI:-}MS_CLIENT_ID=${MS_CLIENT_ID:-}MS_CLIENT_SECRET=${MS_CLIENT_SECRET:-}MS_REDIRECT_URI=${MS_REDIRECT_URI:-}APPLE_CALDAV_URL=${APPLE_CALDAV_URL:-https://caldav.icloud.com}APPLE_USERNAME=${APPLE_USERNAME:-}APPLE_APP_SPECIFIC_PASSWORD=${APPLE_APP_SPECIFIC_PASSWORD:-}DOCUMENT_STORAGE_LOCAL_ENABLED=${DOCUMENT_STORAGE_LOCAL_ENABLED:-false}DOCUMENT_STORAGE_LOCAL_PATH=${DOCUMENT_STORAGE_LOCAL_PATH:-/documents}DOCUMENT_STORAGE_WEBDAV_ENABLED=${DOCUMENT_STORAGE_WEBDAV_ENABLED:-}DOCUMENT_STORAGE_WEBDAV_URL=${DOCUMENT_STORAGE_WEBDAV_URL:-}DOCUMENT_STORAGE_WEBDAV_USERNAME=${DOCUMENT_STORAGE_WEBDAV_USERNAME:-}DOCUMENT_STORAGE_WEBDAV_PASSWORD=${DOCUMENT_STORAGE_WEBDAV_PASSWORD:-}DOCUMENT_STORAGE_WEBDAV_PATH=${DOCUMENT_STORAGE_WEBDAV_PATH:-}DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK=${DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK:-false}SYNC_INTERVAL_MINUTES=${SYNC_INTERVAL_MINUTES:-15}MAX_UPLOAD_MB=${MAX_UPLOAD_MB:-5}GRAVATAR_BASE_URL=${GRAVATAR_BASE_URL:-}ICS_SUBSCRIPTION_ALLOW_PRIVATE_NETWORK=${ICS_SUBSCRIPTION_ALLOW_PRIVATE_NETWORK:-false}RECIPE_PROVIDER_ALLOW_PRIVATE_NETWORK=${RECIPE_PROVIDER_ALLOW_PRIVATE_NETWORK:-false}WASTE_SOURCE_ALLOW_PRIVATE_NETWORK=${WASTE_SOURCE_ALLOW_PRIVATE_NETWORK:-false}NOTIFICATION_ALLOW_PRIVATE_NETWORK=${NOTIFICATION_ALLOW_PRIVATE_NETWORK:-false}DMS_ALLOW_PRIVATE_NETWORK=${DMS_ALLOW_PRIVATE_NETWORK:-true}RATE_LIMIT_WINDOW_MS=${RATE_LIMIT_WINDOW_MS:-60000}RATE_LIMIT_MAX_ATTEMPTS=${RATE_LIMIT_MAX_ATTEMPTS:-5}OIKOS_HTTP_PORT=3000unless-stoppedNotes
Standalone Install
Select an install method, to see config/commands for deploying Yuvomi
Install on Portainer
Import all app templates into your Portainer instance, for easy 1-click deploys
- Ensure both Docker and Portainer are installed, and up-to-date
- Log into your Portainer web UI
- Under Settings → App Templates, paste the below URL
- Head to Home → App Templates, and the list of apps will show up
- Select Yuvomi, fill in any config options, and hit Deploy
Template Import URL
https://raw.githubusercontent.com/Lissy93/portainer-templates/main/templates.json
Show Me
Original stackfile
The compose file this template deploys, straight from its repo:
# Yuvomi - Standalone Docker Compose for Portainer / remote deployment
# Pulls the pre-built image from GitHub Container Registry.
# No git clone required.
#
# Usage:
# 1. Copy this file and the .env section below to your server
# 2. Create a .env file next to this compose file (see below)
# 3. docker compose -f docker-compose.portainer.yml up -d
# 4. docker compose -f docker-compose.portainer.yml exec yuvomi node setup.js
# 5. Open http://<your-host>:3000
#
# In Portainer there is no .env at all: the stack's environment variables are
# handed to Compose for ${...} substitution. That is why every variable this
# container needs is listed explicitly below instead of being pulled in via
# `env_file` - a Git-managed stack has no file to pull from (issue #698). For a
# Git/GitOps stack, point the Compose path at `docs/docker-compose.portainer.yml`
# and set the two required variables in Portainer's own form.
#
# Required .env variables:
# SESSION_SECRET=<random-string-min-32-chars>
# DB_ENCRYPTION_KEY=<random-string-min-32-chars>
#
# Generate secrets:
# openssl rand -hex 32
#
# Strongly recommended:
# BASE_URL=https://yuvomi.example.com # without it, password reset mails
# # are never sent
#
# Every variable below is optional and falls back to the default shown.
# The full list with descriptions lives in .env.example.
services:
yuvomi:
image: ghcr.io/ulsklyc/yuvomi:latest
container_name: yuvomi
restart: unless-stopped
ports:
# Host port from the .env; the app inside the container always stays on 3000.
- "${OIKOS_HTTP_PORT:-3000}:3000"
volumes:
# Named volume keeps its legacy slug so existing Portainer stacks upgrade
# in place instead of orphaning their data on rename.
- oikos_data:/data
# Scheduled and manual backups. Without this volume the files would only
# live inside the container layer and vanish on the next image update.
- oikos_backups:/backups
# Drop-in folder for additional Yuvomi modules. The image creates
# /app/modules, so without this volume anything dropped in there lives in
# the container layer and is gone on the next image update.
- oikos_modules:/app/modules
# Optional: mount a host folder for storing uploaded documents locally.
# Both ends come from the .env so the host folder and the path the app
# writes to cannot drift apart.
# - ${DOCUMENT_STORAGE_LOCAL_DIR:-./documents}:${DOCUMENT_STORAGE_LOCAL_PATH:-/documents}
environment:
- NODE_ENV=production
- PORT=3000
- DB_PATH=/data/yuvomi.db
- BACKUP_DIR=/backups
# Set true to let an admin install third-party modules from Settings into
# the oikos_modules volume (same-origin script from a browser session, no
# file access needed). Off by default; installed modules stay off until an
# admin approves them in a browser session.
- MODULES_ALLOW_WEB_INSTALL=${MODULES_ALLOW_WEB_INSTALL:-false}
- SESSION_SECRET=${SESSION_SECRET:?Set SESSION_SECRET in .env}
- DB_ENCRYPTION_KEY=${DB_ENCRYPTION_KEY:?Set DB_ENCRYPTION_KEY in .env}
# Set to true when behind a reverse proxy with HTTPS (Caddy, nginx, Traefik)
- SESSION_SECURE=${SESSION_SECURE:-false}
# Trust proxy hops (default: 1 for Docker+reverse-proxy setups)
# Set to 'loopback' if running without a reverse proxy
- TRUST_PROXY=${TRUST_PROXY:-1}
# Absolute origin, e.g. https://yuvomi.example.com. REQUIRED for password
# reset mails: the links are only sent when this is set, because the
# request Host header is deliberately not trusted (reset poisoning).
- BASE_URL=${BASE_URL:-}
# Log timestamps and the backup schedule, and the DEFAULT for the household
# zone (which applies wherever a time carries no zone of its own). Since
# v2.34.0 the household zone is also a setting in the app (Settings >
# Account > Appearance > Region) and that setting wins where both exist.
- TZ=${TZ:-UTC}
# Weather (optional) - Open-Meteo (recommended, free, no API key)
- WEATHER_LAT=${WEATHER_LAT:-}
- WEATHER_LON=${WEATHER_LON:-}
- WEATHER_CITY=${WEATHER_CITY:-}
- WEATHER_UNITS=${WEATHER_UNITS:-metric}
# Weather (optional) - OpenWeatherMap (legacy; only if you already use it)
- OPENWEATHER_API_KEY=${OPENWEATHER_API_KEY:-}
- OPENWEATHER_CITY=${OPENWEATHER_CITY:-Berlin}
- OPENWEATHER_UNITS=${OPENWEATHER_UNITS:-metric}
- OPENWEATHER_LANG=${OPENWEATHER_LANG:-en}
# Email / SMTP (optional). Without a host, "forgot password" stays off.
# Can also be configured later under Settings > Household > Email; a value
# set here always wins and the field is then LOCKED in the UI.
#
# That is why none of these may carry a non-empty default: a default of
# 587/starttls would lock the port and encryption fields for every
# Portainer user, including those who never touch SMTP here - anyone on a
# provider using 465/SSL could then no longer set it in the UI at all.
# The server applies its own defaults (587, starttls) when these are empty.
- EMAIL_SMTP_HOST=${EMAIL_SMTP_HOST:-}
- EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-}
- EMAIL_SMTP_SECURE=${EMAIL_SMTP_SECURE:-}
- EMAIL_SMTP_USER=${EMAIL_SMTP_USER:-}
- EMAIL_SMTP_PASS=${EMAIL_SMTP_PASS:-}
- EMAIL_FROM_ADDRESS=${EMAIL_FROM_ADDRESS:-}
- EMAIL_FROM_NAME=${EMAIL_FROM_NAME:-}
# Web push contact address, sent to the push services. The VAPID keys
# themselves are generated on first use. Must be routable: Apple rejects
# localhost and .local with 403.
- VAPID_SUBJECT=${VAPID_SUBJECT:-}
# Single sign-on (optional). OIDC only activates when all four are set.
- OIDC_ISSUER=${OIDC_ISSUER:-}
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID:-}
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET:-}
- OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI:-}
# Some IdPs (Authentik in its default setup among them) send no
# email_verified claim; without this switch they refuse to link accounts.
- OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM=${OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM:-false}
# How Yuvomi authenticates at the token endpoint: client_secret_basic or
# client_secret_post. Empty picks automatically (basic, unless the IdP
# offers post only). Only change it when the IdP answers invalid_client.
- OIDC_TOKEN_AUTH_METHOD=${OIDC_TOKEN_AUTH_METHOD:-}
# Set to false when the IdP serves more people than this household: an
# SSO sign-in then never creates a new account, it only signs in and
# links accounts that already exist.
- OIDC_ALLOW_SIGNUP=${OIDC_ALLOW_SIGNUP:-true}
# Set to false to make SSO the only way in: no login form, no password
# reset. Ignored unless all four OIDC values above are set and an
# administrator account is already linked to the provider.
- AUTH_ALLOW_PASSWORD_LOGIN=${AUTH_ALLOW_PASSWORD_LOGIN:-true}
# Scheduled local backups into the /backups volume above.
- BACKUP_ENABLED=${BACKUP_ENABLED:-true}
- "BACKUP_SCHEDULE=${BACKUP_SCHEDULE:-0 2 * * *}"
- BACKUP_KEEP=${BACKUP_KEEP:-7}
# Additional off-box backup target via WebDAV (Nextcloud and friends).
- WEBDAV_BACKUP_ENABLED=${WEBDAV_BACKUP_ENABLED:-}
- WEBDAV_BACKUP_URL=${WEBDAV_BACKUP_URL:-}
- WEBDAV_BACKUP_USERNAME=${WEBDAV_BACKUP_USERNAME:-}
- WEBDAV_BACKUP_PASSWORD=${WEBDAV_BACKUP_PASSWORD:-}
- WEBDAV_BACKUP_PATH=${WEBDAV_BACKUP_PATH:-}
- WEBDAV_BACKUP_KEEP=${WEBDAV_BACKUP_KEEP:-}
# Currency rates for subscriptions (optional, free tier available)
- FIXER_API_KEY=${FIXER_API_KEY:-}
# Google Calendar (optional)
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- GOOGLE_REDIRECT_URI=${GOOGLE_REDIRECT_URI:-}
- GOOGLE_DRIVE_CLIENT_ID=${GOOGLE_DRIVE_CLIENT_ID:-}
- GOOGLE_DRIVE_CLIENT_SECRET=${GOOGLE_DRIVE_CLIENT_SECRET:-}
- GOOGLE_DRIVE_REDIRECT_URI=${GOOGLE_DRIVE_REDIRECT_URI:-}
# Outlook calendar push via Microsoft Graph (optional)
- MS_CLIENT_ID=${MS_CLIENT_ID:-}
- MS_CLIENT_SECRET=${MS_CLIENT_SECRET:-}
- MS_REDIRECT_URI=${MS_REDIRECT_URI:-}
# Apple Calendar CalDAV (optional)
- APPLE_CALDAV_URL=${APPLE_CALDAV_URL:-https://caldav.icloud.com}
- APPLE_USERNAME=${APPLE_USERNAME:-}
- APPLE_APP_SPECIFIC_PASSWORD=${APPLE_APP_SPECIFIC_PASSWORD:-}
# Local document storage (optional): set to true to store uploaded documents on the mounted /documents folder.
- DOCUMENT_STORAGE_LOCAL_ENABLED=${DOCUMENT_STORAGE_LOCAL_ENABLED:-false}
- DOCUMENT_STORAGE_LOCAL_PATH=${DOCUMENT_STORAGE_LOCAL_PATH:-/documents}
# WebDAV document storage (optional)
- DOCUMENT_STORAGE_WEBDAV_ENABLED=${DOCUMENT_STORAGE_WEBDAV_ENABLED:-}
- DOCUMENT_STORAGE_WEBDAV_URL=${DOCUMENT_STORAGE_WEBDAV_URL:-}
- DOCUMENT_STORAGE_WEBDAV_USERNAME=${DOCUMENT_STORAGE_WEBDAV_USERNAME:-}
- DOCUMENT_STORAGE_WEBDAV_PASSWORD=${DOCUMENT_STORAGE_WEBDAV_PASSWORD:-}
- DOCUMENT_STORAGE_WEBDAV_PATH=${DOCUMENT_STORAGE_WEBDAV_PATH:-}
# Set true only for a WebDAV target on a private/local network (e.g. a
# Nextcloud in the same Docker network). Lifts the SSRF protection.
- DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK=${DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK:-false}
# Sync interval in minutes
- SYNC_INTERVAL_MINUTES=${SYNC_INTERVAL_MINUTES:-15}
- MAX_UPLOAD_MB=${MAX_UPLOAD_MB:-5}
# One-time Gravatar import of a member's profile picture (only a hash of the
# address leaves the server). Off unless set: empty means nothing is sent and
# no button is shown. Opt in with e.g. https://gravatar.com/avatar/ or a
# Libravatar mirror (https only, public host).
- GRAVATAR_BASE_URL=${GRAVATAR_BASE_URL:-}
# Set true only for ICS calendar feeds on a private/local network.
- ICS_SUBSCRIPTION_ALLOW_PRIVATE_NETWORK=${ICS_SUBSCRIPTION_ALLOW_PRIVATE_NETWORK:-false}
# Set true only for recipe provider (Mealie/Tandoor) mirrors on a private/local network.
- RECIPE_PROVIDER_ALLOW_PRIVATE_NETWORK=${RECIPE_PROVIDER_ALLOW_PRIVATE_NETWORK:-false}
# Set true only for a waste collection URL source on a private/local network.
- WASTE_SOURCE_ALLOW_PRIVATE_NETWORK=${WASTE_SOURCE_ALLOW_PRIVATE_NETWORK:-false}
# Set true only for notification channels (Webhook/Gotify/ntfy) on a private/local network.
- NOTIFICATION_ALLOW_PRIVATE_NETWORK=${NOTIFICATION_ALLOW_PRIVATE_NETWORK:-false}
# Default true, anders als die vier darueber: ein DMS ist selbst gehostet und
# steht meist im selben Netz. false erzwingt denselben SSRF-Schutz.
- DMS_ALLOW_PRIVATE_NETWORK=${DMS_ALLOW_PRIVATE_NETWORK:-true}
# Rate limiting
- RATE_LIMIT_WINDOW_MS=${RATE_LIMIT_WINDOW_MS:-60000}
- RATE_LIMIT_MAX_ATTEMPTS=${RATE_LIMIT_MAX_ATTEMPTS:-5}
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
volumes:
oikos_data:
driver: local
oikos_backups:
driver: local
oikos_modules:
driver: local
Or deploy it directly from the source:
git clone https://github.com/ulsklyc/yuvomi
cd yuvomi
docker compose -f docs/docker-compose.portainer.yml up -dMore install options in our documentation, or see ulsklyc/yuvomi for app-specific guidance.
Yuvomi
The self-hosted family planner.
One home instead of many subscriptions.
Tasks, calendar, budget, meals, health and more for a family, a couple or just you, on a
server you own. <a href="https://github.com/ulsklyc/yuvomi/releases"><img src="https://img.shields.io/github/v/release/ulsklyc/yuvomi?style=flat-square&color=6C3AED&label=release" alt="Latest release"></a>
<a href="https://github.com/ulsklyc/yuvomi/stargazers"><img src="https://img.shields.io/github/stars/ulsklyc/yuvomi?style=flat-square&color=6C3AED&label=stars" alt="GitHub stars"></a>
<a href="https://github.com/ulsklyc/yuvomi/pkgs/container/yuvomi"><img src="https://img.shields.io/badge/image-ghcr.io%2Fulsklyc%2Fyuvomi-6C3AED?style=flat-square" alt="Container image ghcr.io/ulsklyc/yuvomi"></a>
<a href="#install"><img src="https://img.shields.io/badge/platforms-amd64%20%7C%20arm64-6C3AED?style=flat-square" alt="Runs on amd64 and arm64"></a>
<a href="https://github.com/ulsklyc/yuvomi/blob/HEAD/LICENSE"><img src="https://img.shields.io/badge/license-MIT-6C3AED?style=flat-square" alt="MIT license"></a> <a href="https://yuvomi.cloud/"><strong>→ Take the tour on yuvomi.cloud</strong></a> ·
<a href="#install"><strong>Install</strong></a> ·
<a href="#documentation">Docs</a> ·
<a href="https://github.com/ulsklyc/yuvomi/blob/HEAD/CHANGELOG.md">Changelog</a> ·
<a href="https://github.com/ulsklyc/yuvomi/blob/HEAD/README.de.md" hreflang="de">Auf Deutsch</a> 20 modules · 27 languages · 0 trackers · 1 SQLite file · 256 MB RAM minimum
<source media="(max-width: 600px) and (prefers-color-scheme: dark)" srcset="docs/screenshots/dashboard-dark-mobile.webp" width="200">
<source media="(max-width: 600px)" srcset="docs/screenshots/dashboard-light-mobile.webp" width="200">
<source media="(prefers-color-scheme: dark)" srcset="docs/screenshots/dashboard-dark-web.webp">
<img src="https://raw.githubusercontent.com/ulsklyc/yuvomi/HEAD/docs/screenshots/dashboard-light-web.webp" alt="The Yuvomi overview: today's events, tasks and shopping for the whole family, with the family, birthdays and rewards below" width="820"> Most households glue their life together from a dozen paid apps, each with its own account, its own subscription and its own copy of your data on someone else's server. Yuvomi puts all of it in one place that belongs to you, running as a container on any home server or NAS.
Many apps, one place
| Instead of juggling… | Yuvomi gives you |
|---|---|
| a to-do & task app | Tasks - Kanban, deadlines, recurring, multi-assignment |
| a family calendar app | Calendar - sync, subscriptions, per-event visibility |
| a meal planner & recipe app | Meals & Recipes - weekly planner with shopping export |
| a grocery-list app | Shopping - shared, aisle-organized lists |
| a budgeting & cost-splitting app | Budget - income, expenses, accounts, savings goals, shared costs with debt simplification |
| a document manager | Documents - searchable family files in folders |
The modules talk to each other
This is the part a folder full of separate apps cannot do:- One import turns the week's meal plan into a shopping list. The next seven days come pre-selected, and every ingredient lands on the shared list, sorted by aisle.
- The last jar out of the pantry goes on the list with one tap. After the shop, one button books what you ticked off back into the pantry, with amount and unit.
- A ticked-off chore pays out. Points on a task go to whoever did it - the assignee, or the person picked when it is ticked off - and are spent in a reward catalog you control.
- A filed receipt hangs on the booking. Upload it once and it belongs to the transaction, the shared expense and the inventory item at the same time.
On the kitchen wall, in every pocket
<source media="(max-width: 600px) and (prefers-color-scheme: dark)" srcset="docs/screenshots/dashboard-wall-dark-web.webp" width="324">
<source media="(max-width: 600px)" srcset="docs/screenshots/dashboard-wall-light-web.webp" width="324">
<source media="(prefers-color-scheme: dark)" srcset="docs/screenshots/dashboard-wall-dark-web.webp">
<img src="https://raw.githubusercontent.com/ulsklyc/yuvomi/HEAD/docs/screenshots/dashboard-wall-light-web.webp" alt="Yuvomi wall mode on a landscape tablet: the time in large type, today's events, tasks and shopping, who is up today, the weather and one-tap kitchen timers" width="600"><source media="(max-width: 600px) and (prefers-color-scheme: dark)" srcset="docs/screenshots/shopping-dark-mobile.webp" width="170">
<source media="(max-width: 600px)" srcset="docs/screenshots/shopping-light-mobile.webp" width="170">
<source media="(prefers-color-scheme: dark)" srcset="docs/screenshots/shopping-dark-mobile.webp">
<img src="https://raw.githubusercontent.com/ulsklyc/yuvomi/HEAD/docs/screenshots/shopping-light-mobile.webp" alt="The shared shopping list on a phone, sorted by aisle: fruit and veg, bakery, dairy, meat and fish" width="207" hspace="12">
- The tablet on the kitchen wall shows today's plan and who is up in wall mode, readable across the room. It has an account of its own: tap a task, pick who did it, and the points go to them. When it sits idle, an Immich screensaver can show your own photos.
- The app on every phone goes on the home screen straight from the browser, no app store. Reminders arrive as push notifications even while it is closed (your server needs HTTPS for that), and the last shopping list you opened stays readable without signal.
- Every member joins by invite link and picks their own password; a child without a phone gets an account created directly. Per family role, each module is full, read only or not at all.
Invited by your family? Open the invite link your admin sent you; it works for seven days. Choose a username if the invite leaves it open, and your own password (none if your household signs in with single sign-on). Then sign in and put Yuvomi on your home screen: tap Install when the app offers it, or on iPhone and iPad choose Share, then Add to Home Screen.
More on yuvomi.cloud
The twenty modules
Switch off what your household doesn't need, and it disappears from everyone's menu. Inventory, Waste collection and Schedule start switched off.
All 20 modules, one line each
Plan - Tasks · Calendar · Rewards · Notes & Contacts · Schedule
Household - Kitchen (Meals · Recipes · Shopping · Pantry) · Housekeeping · Waste collection · Documents · Inventory
People - Health · Birthdays
Finance - Budget
Settings - Family · Reminders · API Tokens · Backup
| Module | In one line |
|---|---|
| Tasks | Kanban board with deadlines, subtasks, recurring chores, comments and a history of who ticked off what. |
| Calendar | Two-way Google and CalDAV sync, Outlook push, subscriptions, holidays and per-event visibility. |
| Rewards | Points from tasks, a parent-approved catalog, an auditable ledger and pocket money per child. |
| Notes & Contacts | Markdown sticky notes with tappable checklists, plus contacts with CardDAV sync and vCard import/export. |
| Schedule | Rotating shifts and fixed weekly timetables, shown as an overlay in the calendar. Off by default. |
| Meals | Weekly drag-and-drop planner with a recipe sidebar and direct export to the shopping list. |
| Recipes | Create and scale recipes, fill meal slots, or mirror a Mealie or Tandoor instance read-only. |
| Shopping | Shared lists sorted by aisle, with swipe gestures and an import from the meal plan. |
| Pantry | Amounts, storage locations and best-before dates, with a reminder before something expires. |
| Housekeeping | Household staff: schedules, check-in/out, billing, chores and supply requests. |
| Waste collection | Pickup schedules per waste type, even "the last Friday", or a subscribed municipal ICS calendar. Off by default. |
| Documents | Searchable family files in folders, stored locally, on WebDAV or in Google Drive. |
| Inventory | What you own, with purchase price, warranty, linked receipts, a service log and recurring deadline reminders. Off by default. |
| Health | Per-member vitals, medications, preventive care, labs, activity, cycle tracking, a fasting journal and a nutrition log, with trend charts. |
| Birthdays | Birthdays and optional name days, with calendar entries, ages and reminders. |
| Budget | Income, expenses, accounts, loans, subscriptions and shared expenses with debt simplification. |
| Family | Member profiles with roles, and invite links where new members pick their own password. |
| Reminders | For tasks, events, medications, warranties, best-before dates, expiring documents and pickups - in-app, push, Gotify, ntfy, webhook or email. |
| API Tokens | Bearer tokens with an OpenAPI 3.1 spec and a built-in MCP endpoint for AI agents. |
| Backup | Manual and scheduled backups with optional WebDAV upload and pre-restore rollback; a backup from another installation restores right in the browser. |
Every module in full detail is in the spec; building your own drop-in module - with its own dashboard widgets, permissions and translations - is covered in the module guide.
Before you commit
What if this project stops? Nothing changes on your machine. It is MIT-licensed and self-hosted, and there is no server of ours anywhere in the path. The container you already pulled keeps running exactly as it does today, with or without us.What if you want your data somewhere else? Everything lives in one SQLite file on your own disk, and copying it is the whole export, as long as documents are stored in the database. Scheduled backups write a restorable archive on top of that, and the documented API pulls anything out in whatever shape you need.
How safe is access from outside? Every account can add a second factor (TOTP, with recovery codes), and an admin can require it for the whole household; new members join through an invite link and pick their own password. With single sign-on through an OIDC provider, password login can be switched off for the household, and a lost phone is signed out from any of your other devices.
What does it cost? Nothing. Yuvomi is free and MIT-licensed. You provide the server; there is no subscription, no upsell and no paid tier.
Does it phone home? On its own, it only asks GitHub whether a newer version exists, and blocking that breaks nothing. Anything else waits until you use or switch on a feature that needs it; every connection is listed in the Install section, under Requirements, network and your data.
Install
From your NAS app store - TrueNAS SCALE, Umbrel or Unraid: search for Yuvomi in the catalog and install, no terminal.With Docker on any server. The image
ghcr.io/ulsklyc/yuvomi:latest is about 500 MB and runs
on amd64 and arm64 (Raspberry Pi 4/5); Yuvomi needs one port, 3000 by default.curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/.env.example
cp .env.example .env
openssl rand -hex 32 # SESSION_SECRET
openssl rand -hex 32 # DB_ENCRYPTION_KEYNow open.envand replace bothREPLACE_WITH_…placeholders with the two values, in that order, and write the second one down: it is the database key, and a lost or changed key never opens the database again, not by you and not by us. With a placeholder left in, Yuvomi refuses to start. To run without encryption, clear theDB_ENCRYPTION_KEYline instead of filling it.
docker compose up -dOpen
http://localhost:3000 and create your admin account. Podman, Proxmox, HTTPS, backups and
troubleshooting, step by step: the install guide on yuvomi.cloud
and the installation guide.Podman, Proxmox, the guided setup and the encryption key
- Podman - fetch
podman-compose.ymlinstead ofdocker-compose.ymland start it with
podman compose -f podman-compose.yml up -d; it carries the SELinux :Z volume labels that
RHEL, Fedora and CentOS Stream need.- Page does not load -
docker compose logs(on Podman,
podman compose -f podman-compose.yml logs) usually names the reason, and the
troubleshooting guide covers the common ones.- Proxmox - the same steps run inside a small Debian LXC: see the
- Encryption key - optional, but there is no way back. The guided setup and Umbrel generate
- Guided setup - a localized setup wizard in your browser. It detects Docker or Podman, sets
```bash git clone https://github.com/ulsklyc/yuvomi.git && cd yuvomi node tools/installer/install-server.js ```
Open http://localhost:8090 on the server itself; the wizard answers nowhere else. From another device, open a tunnel first,
ssh -L 8090:localhost:8090 user@server, then open the
same address there. Needs Node.js 22.14+ or 23.6+ on the host; the container ships its own
Node 24.Requirements, network and your data
- Browsers - everything as designed from Chrome and Edge 117, Firefox 129 and Safari 17.5. Down to Chrome 87, Firefox 79 and Safari 14.1 (iOS 14.5) it still starts and scrolls, with a plainer look and some features missing (measured 21 September 2026).
- Writes - four volumes you own: data, backups, modules, documents.
- Outbound - on its own, one update check against the GitHub releases API. Block it and nothing breaks, only the hint about a newer version stays away. Everything else reaches out only when you use or switch on a feature that needs it:
- Your LAN - calendar subscriptions, notification channels (webhook, Gotify, ntfy), WebDAV document storage, recipe mirrors and waste-collection feeds on private or internal addresses stay blocked until you opt in (how). Paperless and Papra are the exception: they may reach the LAN out of the box.
- Your data - one SQLite file at
/data/yuvomi.db, plus the folder, WebDAV or Drive if you moved documents there.
Before you go live: health data, Google Drive sharing and GDPR
Health is not a medical device. No diagnostic claims are made. Health data is sensitive, so enable database encryption (DB_ENCRYPTION_KEY, SQLCipher).External document storage needs its own backup. Database backups hold document metadata and links, not binaries stored in a local folder, on WebDAV, or in Google Drive; back up the selected target separately. Yuvomi visibility settings only control access through Yuvomi. Anyone with access to the connected Yuvomi/Documents Google Drive folder can view all files stored there.Self-hosting in a GDPR context? If you run Yuvomi in the EU/EEA and process other people's data, read privacy for self-hosters before going live. It covers third-country assessments for every external service, data-processing-agreement notes, log-retention guidance and a records-of-processing template.
Coming from Oikos, or seeing oikos in an app store? Same app, renamed.
Yuvomi was renamed from Oikos to avoid a trademark conflict with an unrelated product. Same code, same data, same maintainer.
- Old links (
github.com/ulsklyc/oikos) redirect here automatically. - The Docker image moved to
ghcr.io/ulsklyc/yuvomi; the oldghcr.io/ulsklyc/oikoskeeps working, so update at your convenience. - Existing data and settings are fully preserved on upgrade.
- Some catalog slugs keep the technical name
oikos(e.g. Unraidoikos-…) so existing installations upgrade seamlessly. Search for Yuvomi; an entry still shown as oikos is the same app.
Under the hood
- No build step - pure ES modules and plain CSS. No bundler, no transpiler, no framework, no runtime CDN.
- Feels like a native app - built to Apple's interface guidelines: the system font, capsule buttons, grouped lists and spring motion, with WCAG AA contrast checked in light and dark.
- Privacy first - fully self-hosted, optional SQLCipher AES-256 database encryption, zero telemetry.
- Sign-in for a whole household - two-factor authentication, invite links, optional password reset by email and single sign-on with any OIDC provider; see how safe access from outside is.
- Your language, detected automatically. A separate household setting decides the language of entries Yuvomi creates itself, so an exported calendar speaks your household's language instead of English.
- Stack - Node.js and Express with SQLite (SQLCipher), one container for Docker or Podman, a PWA on every phone.
Documentation
- See it - Tour and screenshots on yuvomi.cloud · Install guide on yuvomi.cloud
- Run it - Installation · Security · Privacy for self-hosters · Notification webhooks · Immich screensaver
- Build on it - Spec & data model · Third-party modules · Contributing
- Follow the project - Changelog · Roadmap · Decisions · Scope · Backlog · Releasing
User guide (community-maintained): @Kyrodan writes a user documentation site in his own repository. It is not part of this project and can lag behind a release, so where it and the sources above disagree, the ones above are right.
One home for your household. Yours to keep.
Install it once. No account with us, no subscription,<br>
and nothing of ours between your household and its data.
<a href="#install"><strong>→ Install it</strong></a> ·
<a href="https://yuvomi.cloud/"><strong>Take the tour</strong></a> ·
<a href="https://github.com/ulsklyc/yuvomi/discussions"><strong>Ask a question</strong></a>
MIT licensed, see LICENSE. More at yuvomi.cloud.
Check the logs first
Nine times out of ten the logs tell you exactly what went wrong.
- In Portainer, go to Containers, click the container, then Logs. Or run
docker logs <container> - Exit codes help too:
137means killed, usually out of memory.126or127means the command inside the image is broken.
Image won't pull
Test the pull directly on the host: docker pull ghcr.io/ulsklyc/yuvomi:latest
- "manifest unknown" means the tag no longer exists. This template uses
latest, so try pinning a specific version instead. - "toomanyrequests" is the Docker Hub rate limit. Log in with
docker loginto raise it. - "no space left on device" means a full disk. Reclaim space with
docker system prune
"exec format error"
This means the image was built for a different CPU architecture than your server.
- This image supports:
amd64, arm64 - Check yours with
uname -m: x86_64 is amd64, aarch64 is arm64. Raspberry Pi and other ARM boards are the usual culprits.
Container keeps restarting
The unless-stopped restart policy relaunches the app after every crash, so the real error can scroll past.
- Check the logs right after a restart, the last few lines before it died are the useful ones.
- Get the exit code with
docker inspect <container> --format '{{.State.ExitCode}}' - Still stuck? Redeploy once with the restart policy set to
noso the failure stays visible.
Stack won't deploy
Compose stacks fail fast on small mistakes, and Portainer shows the reason just above the editor.
- YAML only accepts spaces for indentation, a single tab breaks the whole file.
Raise an issue
Found something which isn't working as it should? Here's how to report it.
- Bug within the app: Open an issue on ulsklyc/yuvomi
- Template not working: Open an issue on ulsklyc/yuvomi
- This website not working: Open an issue on lissy93/portainer-templates
A Compose stack
Yuvomi is a Compose stack, a set of containers defined in one file and brought up together by Portainer, then started and stopped as a single app.
The app image
An image is the app packed up ready to go, everything Yuvomi needs bundled into one download. This template pulls ghcr.io/ulsklyc/yuvomi:latest, which Docker fetches once (about 132 MB) and then starts your own copy from.
Where the image comes from
Docker pulls its images from registries, public libraries of ready-built apps. Yuvomi's comes from the GitHub Container Registry, published by ulsklyc.
Version tags
The bit after the colon in the image name is the version tag. Here it's latest, which always points at the newest build, so a redeploy can bump you to a newer release without you asking. Pin a specific tag if you would rather stay on one version.
Which machines it runs on
Every image is built for particular CPU types. This one ships for amd64, arm64, so it runs on both regular x86 servers and ARM boards like a Raspberry Pi.
Volumes
A volume is where Yuvomi keeps its files so they survive an update or a restart. Without one, anything it saves would sit inside the container and vanish the moment it's recreated. This template mounts:
/datakept in theoikos_datavolume Docker manages/backupskept in theoikos_backupsvolume Docker manages/app/moduleskept in theoikos_modulesvolume Docker manages
Environment variables
Environment variables are the settings you hand over when you deploy, things like a password or a timezone. Yuvomi takes 76 of them, and 2 need a value before it'll start properly:
NODE_ENV, defaults toproductionPORT, defaults to3000DB_PATH, defaults to/data/yuvomi.dbBACKUP_DIR, defaults to/backupsMODULES_ALLOW_WEB_INSTALL, defaults tofalseSESSION_SECRET, needs a value. At least 32 random characters. Generate one with: openssl rand -hex 32. Changing it later signs everyone out once.DB_ENCRYPTION_KEY, needs a value. At least 32 random characters. Generate one with: openssl rand -hex 32. Keep a copy: the database and its backups only open with exactly this key.SESSION_SECURE, defaults tofalseTRUST_PROXY, defaults to1BASE_URL, pulled from your own environment. The address your household uses, e.g. https://yuvomi.example.com. Without it, password reset mails are never sent.TZ, defaults toUTCWEATHER_LAT, pulled from your own environmentWEATHER_LON, pulled from your own environmentWEATHER_CITY, pulled from your own environmentWEATHER_UNITS, defaults tometricOPENWEATHER_API_KEY, pulled from your own environmentOPENWEATHER_CITY, defaults toBerlinOPENWEATHER_UNITS, defaults tometricOPENWEATHER_LANG, defaults toenEMAIL_SMTP_HOST, pulled from your own environmentEMAIL_SMTP_PORT, pulled from your own environmentEMAIL_SMTP_SECURE, pulled from your own environmentEMAIL_SMTP_USER, pulled from your own environmentEMAIL_SMTP_PASS, pulled from your own environmentEMAIL_FROM_ADDRESS, pulled from your own environmentEMAIL_FROM_NAME, pulled from your own environmentVAPID_SUBJECT, pulled from your own environmentOIDC_ISSUER, pulled from your own environmentOIDC_CLIENT_ID, pulled from your own environmentOIDC_CLIENT_SECRET, pulled from your own environmentOIDC_REDIRECT_URI, pulled from your own environmentOIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM, defaults tofalseOIDC_TOKEN_AUTH_METHOD, pulled from your own environmentOIDC_ALLOW_SIGNUP, defaults totrueAUTH_ALLOW_PASSWORD_LOGIN, defaults totrueBACKUP_ENABLED, defaults totrueBACKUP_SCHEDULE, defaults to0 2 * * *BACKUP_KEEP, defaults to7WEBDAV_BACKUP_ENABLED, pulled from your own environmentWEBDAV_BACKUP_URL, pulled from your own environmentWEBDAV_BACKUP_USERNAME, pulled from your own environmentWEBDAV_BACKUP_PASSWORD, pulled from your own environmentWEBDAV_BACKUP_PATH, pulled from your own environmentWEBDAV_BACKUP_KEEP, pulled from your own environmentFIXER_API_KEY, pulled from your own environmentGOOGLE_CLIENT_ID, pulled from your own environmentGOOGLE_CLIENT_SECRET, pulled from your own environmentGOOGLE_REDIRECT_URI, pulled from your own environmentGOOGLE_DRIVE_CLIENT_ID, pulled from your own environmentGOOGLE_DRIVE_CLIENT_SECRET, pulled from your own environmentGOOGLE_DRIVE_REDIRECT_URI, pulled from your own environmentMS_CLIENT_ID, pulled from your own environmentMS_CLIENT_SECRET, pulled from your own environmentMS_REDIRECT_URI, pulled from your own environmentAPPLE_CALDAV_URL, defaults tohttps://caldav.icloud.comAPPLE_USERNAME, pulled from your own environmentAPPLE_APP_SPECIFIC_PASSWORD, pulled from your own environmentDOCUMENT_STORAGE_LOCAL_ENABLED, defaults tofalseDOCUMENT_STORAGE_LOCAL_PATH, defaults to/documentsDOCUMENT_STORAGE_WEBDAV_ENABLED, pulled from your own environmentDOCUMENT_STORAGE_WEBDAV_URL, pulled from your own environmentDOCUMENT_STORAGE_WEBDAV_USERNAME, pulled from your own environmentDOCUMENT_STORAGE_WEBDAV_PASSWORD, pulled from your own environmentDOCUMENT_STORAGE_WEBDAV_PATH, pulled from your own environmentDOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK, defaults tofalseSYNC_INTERVAL_MINUTES, defaults to15MAX_UPLOAD_MB, defaults to5GRAVATAR_BASE_URL, pulled from your own environmentICS_SUBSCRIPTION_ALLOW_PRIVATE_NETWORK, defaults tofalseRECIPE_PROVIDER_ALLOW_PRIVATE_NETWORK, defaults tofalseWASTE_SOURCE_ALLOW_PRIVATE_NETWORK, defaults tofalseNOTIFICATION_ALLOW_PRIVATE_NETWORK, defaults tofalseDMS_ALLOW_PRIVATE_NETWORK, defaults totrueRATE_LIMIT_WINDOW_MS, defaults to60000RATE_LIMIT_MAX_ATTEMPTS, defaults to5OIKOS_HTTP_PORT, defaults to3000. Host port for the web UI
Restart policy
The restart policy here is unless-stopped, so Docker restarts Yuvomi after a crash or reboot, but leaves it off when you stop it on purpose. You can change this on the deploy screen. The choices are no (never restart), on-failure (only after a crash), unless-stopped (restart unless you stop it), and always (bring it back no matter what).
Health check
A health check is how Docker tells whether Yuvomi is really working, not just switched on. It runs node -e require('http').get('http://localhost:3000/health', r => process.exit(r.statusCode === 200 ? 0 : 1)) every 30s and flags the container as unhealthy if that keeps failing.
Networking
Nothing custom is set, so Yuvomi sits on Docker's default bridge network: its own private space that reaches the outside world only through the ports it publishes.
Container name
Once it's deployed, Portainer names the container yuvomi. That's what you'll spot in the containers list and use in commands like docker logs yuvomi.
Platform
The platform is linux, the kind of system the container is built to run on. Docker and Portainer handle this on a normal Linux server.
Open source license
Yuvomi is open source, released under the MIT license. In plain terms the code is out in the open, so you're free to run it and change it to fit what you need.
Portainer app templates
Zooming out, this whole page comes from a Portainer app template: a short recipe telling Portainer how to set Yuvomi up. Add the template list to Portainer once, then deploying Yuvomi is a click rather than a wall of config.