Skip to content

snachodog/medicine-cabinet

Dependabot Updates

Medicine Cabinet

Medicine Cabinet is a self-hosted web app for tracking your household's medications, prescriptions, and dose history — running entirely on your own server.

Inspired by tools like Snipe-IT, it treats medications as trackable assets assigned to people. Built for families, caregivers, or anyone managing health items at home.


Features

Household & Profiles

  • Multi-person households — manage medications for multiple people under one account
  • Household sharing — grant other accounts access to a person's records by username; revoke at any time
  • Person profiles — store allergies and notes per household member
  • Allergy tracking — allergy information is prominently displayed and included in PDF exports

Medications & Prescriptions

  • Medication management — create, edit, and deactivate medications with name, dosage, type (OTC / supplement / Rx), schedule, and notes
  • Prescription tracking — link prescriptions to Rx medications; track fill dates, scripts remaining, next eligible date, expiration date, prescriber, pharmacy, and co-pay
  • Dose logging — record when doses are taken; view history and streaks per medication
  • Medication catalog — search a built-in drug reference to pre-fill medication fields by name

Contacts

  • Provider directory — save prescribers with specialty, phone, address, and website; autofills prescription forms
  • Pharmacy directory — save pharmacies with contact info; autofills prescription forms

Exports & Integrations

  • PDF medication report — generate a printable report per person listing all active medications, suitable for handing to a provider or emergency services
  • Calendar feed (ICS) — subscribe to a per-account .ics feed in any calendar app (Google Calendar, Apple Calendar, Outlook) with pickup events and refill reminders; or download a one-time snapshot

Notifications & Reminders

  • Email alerts — receive email warnings 7 and 30 days before a prescription's expiration date (requires SMTP configuration)
  • ntfy push notifications — send refill reminders and low-script alerts to any ntfy topic
  • Refill reminders — configurable advance notice before a prescription's next eligible pickup date
  • Expiration highlighting — prescriptions approaching or past expiration are flagged in the UI

Access & Account Management

  • Local accounts — username/password registration with strength requirements (8+ chars, upper, lower, digit, special)
  • SSO / OIDC login — optional single sign-on via any OpenID Connect provider (Google, Authentik, Keycloak, etc.)
  • Toggleable registration — open registration (default) or invite-only mode controlled by an environment variable
  • Invite codes — logged-in users can generate single-use invite codes with optional expiry; required when registration is closed
  • Account self-service — users can change their username and password from the Account settings tab
  • Installable PWA — install Medicine Cabinet as an app on mobile and desktop; cached pages work offline

Security & Administration

  • Passwords protected by bcrypt — plaintext passwords are never stored and cannot be recovered from the database
  • User isolation — every request verifies account access; one user cannot read another's data unless explicitly shared
  • httpOnly cookie auth — JWT session tokens stored in HttpOnly, SameSite=Lax cookies; never exposed to JavaScript
  • Token revocation — logout invalidates the session token immediately
  • Rate limiting — login and registration endpoints are rate-limited to prevent brute force
  • Security headersX-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy on every response
  • Audit log — all create/update/delete events are logged and visible to account holders

Developer / API

  • REST API — all data accessible via the FastAPI backend; interactive docs at /api/docs
  • Alembic migrations — schema migrations run automatically on startup; no manual steps

Tech Stack

Layer Technology
Frontend React 18 + React Router 7 + Tailwind CSS 4
Backend FastAPI (Python 3.12)
ORM SQLAlchemy
Migrations Alembic (auto-runs on startup)
Database PostgreSQL 15
Self-hosting Docker + Docker Compose
Image dogiakos/medicine-cabinet:latest

Getting Started

Prerequisites

1. Download the compose file

curl -O https://raw.githubusercontent.com/snachodog/medicine-cabinet/main/docker-compose.yml
curl -O https://raw.githubusercontent.com/snachodog/medicine-cabinet/main/.env.example

Or clone the repo:

git clone https://github.com/snachodog/medicine-cabinet.git
cd medicine-cabinet

2. Configure environment variables

cp .env.example .env

Edit .env. At minimum, set secure values for the database password and JWT secret:

openssl rand -hex 24   # for POSTGRES_PASSWORD
openssl rand -hex 32   # for SECRET_KEY

Your minimal .env:

POSTGRES_PASSWORD=your-strong-password
POSTGRES_USER=medicabinet
POSTGRES_DB=medicabinet_db
SECRET_KEY=your-long-random-secret
ACCESS_TOKEN_EXPIRE_MINUTES=60

Local development over plain HTTP? The auth cookie has Secure=true by default, which browsers refuse to store over HTTP. If you are running the app locally without a TLS proxy, add COOKIE_SECURE=false to your .env or login will silently fail. This setting must be true (or omitted) in any internet-facing deployment.

See the Configuration reference below for all available options.

3. Start

docker compose up -d

Database migrations run automatically on startup.

4. Open the app

Register the first account on the login page.

Updating

docker compose pull
docker compose up -d

Migrations are applied automatically — no manual steps required between versions.


Configuration Reference

All configuration is via environment variables in .env. Only the required variables are needed for basic operation; everything else is optional.

Required

Variable Description
POSTGRES_PASSWORD Database password
SECRET_KEY JWT signing secret — use a long random string

Optional — Core

Variable Default Description
POSTGRES_USER medicabinet Database username
POSTGRES_DB medicabinet_db Database name
ACCESS_TOKEN_EXPIRE_MINUTES 60 How long login sessions last
REGISTRATION_ENABLED true Set to false to require an invite code to register
COOKIE_SECURE true Adds the Secure flag to auth cookies. Keep true for HTTPS. Set to false for local HTTP dev - browsers drop Secure cookies over HTTP, causing login to fail.

Optional — SSO / OIDC

All three OIDC variables must be set to enable SSO. The login page shows an SSO button automatically when enabled.

Variable Description
OIDC_ISSUER Provider discovery base URL (e.g. accounts.google.com)
OIDC_CLIENT_ID Client ID from your identity provider
OIDC_CLIENT_SECRET Client secret from your identity provider
OIDC_PROVIDER_NAME Label shown on the SSO button (default: SSO)
OIDC_SCOPES Space-separated scopes (default: openid email profile)

Your identity provider's redirect URI must be set to:

http(s)://your-domain/api/auth/oidc/callback

Optional — Email notifications

All five SMTP variables must be set to enable email alerts.

Variable Description
SMTP_HOST SMTP server hostname, e.g. smtp.gmail.com
SMTP_PORT SMTP port (default: 587)
SMTP_USER SMTP login username
SMTP_PASSWORD SMTP login password
SMTP_FROM From address for outgoing emails

Once configured, users opt in per-account under Settings → Notifications and provide their email address there.


Roadmap

  • Dashboard view — expiring prescriptions, upcoming refills, recent activity at a glance
  • CSV import/export for bulk medication management
  • Password reset via email

Privacy & Security

Medicine Cabinet is designed to be self-hosted so sensitive health data stays on your own server and never passes through a third-party service. You control the database, the backups, and who has access.

Security measures

Area Details
Passwords Stored as bcrypt hashes with a random salt. Plaintext passwords are never written to disk and cannot be recovered from the database.
User isolation Every API request verifies that the requesting account has been granted access to the person's data. One user cannot read another's medications, logs, or prescriptions unless explicitly shared.
Auth cookies JWT session tokens are stored in HttpOnly, SameSite=Lax cookies — not accessible to JavaScript. The Secure flag is enabled by default (COOKIE_SECURE=true) so cookies are only transmitted over HTTPS.
Token revocation Logging out immediately invalidates the session token.
Rate limiting Login and registration endpoints are rate-limited to slow brute-force attempts.
Transport Designed to run behind a TLS-terminating reverse proxy (Cloudflare, Caddy, nginx). The Docker image does not expose plain HTTP to the internet.

Recommendations for self-hosters

  • Enable HTTPS - run behind Cloudflare, Caddy, or an nginx reverse proxy with a TLS certificate. Do not expose port 8000 directly to the internet.
  • Enable disk/volume encryption on the host to protect database files if physical media is ever lost or seized.
  • Restrict database access - the Postgres port is not published externally by default in docker-compose.yml. Keep it that way.
  • Keep backups encrypted - if you back up the Postgres volume, encrypt the backup at rest.
  • Use a strong SECRET_KEY - generate with openssl rand -hex 32. Rotating it invalidates all active sessions.

OIDC / SSO note

OIDC accounts are provisioned on first login using the verified email address returned by the identity provider. No unverified auto-provisioning occurs. The identity provider is responsible for authenticating the user — Medicine Cabinet trusts the claims in the OIDC token.


License

MIT — © 2026 Steven Dogiakos


Acknowledgments

  • Snipe-IT for the asset/consumable management model
  • The open-source community that makes self-hosting practical

About

A self-hosted web app to track medicines, prescriptions, etc

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors