- **Locations** - Location management with OSM search integration, category filtering, frequent locations
- **Weather** - Dashboard weather widget with temperature, conditions, and contextual rain warnings
- **Settings** - Accent color picker (5 presets), first day of week, weather city, ntfy push notifications, TOTP two-factor auth, auto-lock, password management
- **Notifications** - ntfy push notifications for reminders (configurable per-user)
- **Dashboard** - At-a-glance overview with today's events, upcoming todos, active reminders, and project stats
- **Todos** - Task management with priorities, due dates, and completion tracking
- **Calendar** - Full interactive calendar (month/week/day views) with drag-and-drop event rescheduling
- **Projects** - Project boards with nested task lists, status tracking, and progress indicators
- **Reminders** - Time-based reminders with dismiss functionality
- **People** - Contact directory with relationship tracking and task assignment
- **Locations** - Location management with categories
- **Weather** - Dashboard weather widget with temperature, conditions, and rain warnings
- **Settings** - Customizable accent color, upcoming days range, weather city, and PIN management
@ -47,7 +48,7 @@ A self-hosted personal life administration app with a dark-themed UI. Manage you
```bash
cp .env.example .env
```
Edit `.env` and set secure values (see [Production Hardening](#production-hardening) below for generation commands):
Edit `.env` and set secure values:
```env
POSTGRES_USER=umbra
POSTGRES_PASSWORD=your-secure-password
@ -66,7 +67,7 @@ A self-hosted personal life administration app with a dark-themed UI. Manage you
4. **Open the app**
Navigate to `http://localhost` in your browser. On first launch you'll be prompted to create a username and password.
Navigate to `http://localhost` in your browser. On first launch you'll be prompted to create a PIN.
## Architecture
@ -80,16 +81,15 @@ A self-hosted personal life administration app with a dark-themed UI. Manage you
+-------+-------+
| Nginx |
| (frontend) |
| non-root:8080 |
+---+-------+---+
| |
static | | /api/*
files | | (rate-limited auth)
files | |
v v
+---+-------+---+
| FastAPI |
| (backend) |
| non-root |
| port 8000 |
+-------+-------+
|
+-------+-------+
@ -99,77 +99,29 @@ A self-hosted personal life administration app with a dark-themed UI. Manage you
+---------------+
```
- **Frontend** is built as static files and served by `nginxinc/nginx-unprivileged`. Nginx also reverse-proxies API requests to the backend with rate limiting on auth endpoints.
- **Backend** runs Alembic migrations on startup as a non-root user (`appuser`), then serves the FastAPI application with `--no-server-header`.
- **Frontend** is built as static files and served by Nginx. Nginx also reverse-proxies API requests to the backend.
- **Backend** runs Alembic migrations on startup, then serves the FastAPI application.
- **Database** uses a named Docker volume (`postgres_data`) for persistence.
- **Backend port 8000 is not exposed externally** — only accessible via the internal Docker network.
## Security
### Hardened by default
- **Non-root containers** — both backend (`appuser:1000`) and frontend (`nginx-unprivileged`) run as non-root
- **No external backend port** — port 8000 is internal-only; all traffic flows through nginx
- **Server version suppression** — `server_tokens off` (nginx) and `--no-server-header` (uvicorn)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.