No description
Find a file
2026-06-03 12:28:23 +02:00
.forgejo chore: change pr merge workflow 2026-01-29 14:30:09 +01:00
assets Improve member view table behavior+style, fix config settings (#493) 2026-05-08 15:04:53 +02:00
config chore(ci): make test workflow faster with test --stale 2026-06-02 23:35:39 +02:00
docs Remove stale documentation of removed join_date future-date restriction 2026-05-12 23:16:31 +02:00
lib feat(custom-field): let admins set join_description with a link-syntax hint 2026-06-03 12:28:23 +02:00
priv feat(custom-field): let admins set join_description with a link-syntax hint 2026-06-03 12:28:23 +02:00
rauthy-bootstrap fix(auth): trigger RP-initiated logout at OIDC provider 2026-06-01 19:59:52 +02:00
rel/overlays/bin Run bootstrap seeds in production; add RUN_DEV_SEEDS support 2026-03-09 15:16:02 +01:00
test feat(custom-field): let admins set join_description with a link-syntax hint 2026-06-03 12:28:23 +02:00
.credo.exs CI: run Credo in strict mode 2026-03-04 16:21:15 +01:00
.deps_audit_ignore chore(deps): suppress cowlib advisory and bump bandit, cowboy, plug 2026-05-20 16:16:27 +02:00
.dialyzer_ignore.exs feat(dialyzer): add typecheck stage to full CI pipelines 2026-06-01 23:45:07 +02:00
.dockerignore Add Release scripts & Dockerfile 2025-05-22 02:12:20 +02:00
.drone.jsonnet feat(dialyzer): add typecheck stage to full CI pipelines 2026-06-01 23:45:07 +02:00
.editorconfig configure renovate 2025-05-14 16:39:57 +02:00
.env.example feat(rauthy): auto-seed mv OIDC client via bootstrap dir 2026-06-01 19:06:14 +02:00
.formatter.exs chore(AshAuthenticationPhoenix): added library and updated ressources testing password strategy 2025-07-02 17:03:37 +02:00
.gitignore feat(dialyzer): add typecheck stage to full CI pipelines 2026-06-01 23:45:07 +02:00
.igniter.exs chore(AshAuthenticationPhoenix): added library and updated ressources testing password strategy 2025-07-02 17:03:37 +02:00
.sobelow-conf Add basic CI setup (#30) 2025-04-28 14:24:30 +02:00
.tool-versions chore(deps): update dependency just to v1.50.0 2026-05-01 00:14:49 +00:00
CHANGELOG.md CHANGELOG.md aktualisiert 2026-05-08 15:20:18 +02:00
CODE_GUIDELINES.md Improve member view table behavior+style, fix config settings (#493) 2026-05-08 15:04:53 +02:00
DESIGN_GUIDELINES.md Improve member view table behavior+style, fix config settings (#493) 2026-05-08 15:04:53 +02:00
docker-compose.prod.yml fix database volume path for PG 18 2026-05-04 21:49:21 +02:00
docker-compose.yml feat(rauthy): auto-seed mv OIDC client via bootstrap dir 2026-06-01 19:06:14 +02:00
Dockerfile fix: update debian image to trixie (stable) to fix imprintor glibc version mismatch 2026-02-23 18:13:37 +01:00
Justfile chore(ci): make test workflow faster with test --stale 2026-06-02 23:35:39 +02:00
LICENSE feat: add license closes #150 2025-10-02 17:12:06 +02:00
mix.exs feat(dialyzer): add typecheck stage to full CI pipelines 2026-06-01 23:45:07 +02:00
mix.lock feat(dialyzer): add typecheck stage to full CI pipelines 2026-06-01 23:45:07 +02:00
README.md feat(rauthy): auto-seed mv OIDC client via bootstrap dir 2026-06-01 19:06:14 +02:00
renovate.json fix renovate syntax 2026-03-09 13:14:38 +01:00
renovate_backend_config.js configure renovate 2025-05-14 16:39:57 +02:00

Mila

Mila — simple, usable, self-hostable membership management for small to mid-sized clubs.

Build Status License

🚧 Project Status

⚠️ First Version — Expect breaking changes.
Contributions and feedback are welcome!

Overview

Mila is a free and open-source membership management tool designed for real club needs.
It is self-hosting friendly, aims for accessibility and GDPR compliance, and focuses on usability instead of feature overload.

💡 Why Mila?

Most membership tools for clubs are either:

  • Too complex — overloaded with features small and mid-sized clubs dont need
  • Too expensive — hidden fees, closed ecosystems, vendor lock-in
  • Too rigid — no way to adapt fields, processes, or roles to your clubs reality

Mila is different:

  • Simple: Focused on what clubs really need — members, dues, communication.
  • Usable: Clean, accessible UI, GDPR-compliant, designed with everyday volunteers in mind.
  • Flexible: Customize what data you collect about members, role-based permissions, and self-service for members.
  • Truly open: 100% free and open source — no lock-in, transparent code, self-host friendly.

Our philosophy: software should help people spend less time on administration and more time on their community.

User Documentation (German)

You can find our documentation for users here: https://wiki.local-it.org/s/mila-user-dokumentation

🔑 Features

  • Manage member data with ease
  • Membership fees & payment status tracking
  • Full-text search with fuzzy matching
  • Sorting & filtering
  • Roles & permissions (RBAC system with 4 permission sets)
  • Custom fields (flexible per club needs)
  • SSO via OIDC (works with Authentik, Rauthy, Keycloak, etc.)
  • Sidebar navigation (standard-compliant, accessible)
  • Global settings management
  • Self-service & online application
  • Accessibility improvements (WCAG 2.1 AA compliant keyboard navigation)
  • Email sending
  • Integration of Accounting-Software (Vereinfacht)

🚀 Quick Start (Development)

Prerequisites

We recommend using asdf for managing tool versions.

  • Tested with: asdf 0.16.5
  • Required versions are documented in .tool-versions in this repo
Install system dependencies (Debian/Ubuntu)
# Debian 12
apt-get -y install build-essential autoconf m4 libncurses-dev libwxgtk3.2-dev libwxgtk-webview3.2-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils openjdk-17-jdk icu-devtools bison flex pkg-config

# Ubuntu 24
apt-get -y install build-essential autoconf m4 libwxgtk3.2-dev libwxgtk-webview3.2-dev libgl1-mesa-dev libglu1-mesa-dev libpng-dev libssh-dev unixodbc-dev xsltproc fop libxml2-utils libncurses-dev openjdk-11-jdk icu-devtools bison flex libreadline-dev
Install asdf
mkdir ~/.asdf
cd ~/.asdf
wget https://github.com/asdf-vm/asdf/releases/download/v0.16.5/asdf-v0.16.5-linux-amd64.tar.gz
tar -xvf asdf-v0.16.5-linux-amd64.tar.gz
ln -s ~/.asdf/asdf ~/.local/bin/asdf

Then follow the official “Shell Configuration” steps in the asdf docs.

Fish example (~/.config/fish/config.fish):

asdf completion fish > ~/.config/fish/completions/asdf.fish
set -gx PATH "$HOME/.asdf/shims" $PATH

Bash example (~/.bash_profile and ~/.bashrc):

export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH"
. <(asdf completion bash)

Install project dependencies

git clone https://git.local-it.org/local-it/mitgliederverwaltung.git mila
cd mila
asdf plugin add elixir
asdf plugin add erlang
asdf plugin add just
asdf install

# Inside the repo folder:
mix local.hex 
mix archive.install hex phx_new 

Note: running mix local.hex must be done inside the repo folder,
because .tool-versions defines the Erlang/Elixir versions.

Run the app

  1. Copy env file:

    cp .env.example .env
    

    The dev OIDC_CLIENT_SECRET is already preset — no manual GUI step needed.

  2. Start everything (database, Mailcrab, Rauthy, app):

    just run
    
  3. Services will be available at:

🔐 Testing SSO locally

A local Rauthy instance is provided in dev. The mv client is auto-seeded from rauthy-bootstrap/clients.json on first start (and after docker compose down -v), so the secret in .env.example always matches.

Rauthy admin UI: http://localhost:8080 — login admin@localhost, password from BOOTSTRAP_ADMIN_PASSWORD_PLAIN in docker-compose.yml.

OIDC with other providers (Authentik, Keycloak, etc.)

Mila works with any OIDC-compliant provider. The internal strategy is named :oidc — it works with any OIDC-compliant provider.

Important: The redirect URI must always end with /auth/user/oidc/callback.

Example for Authentik:

  1. Create an OAuth2/OpenID Provider in Authentik
  2. Set the redirect URI to: https://your-domain.com/auth/user/oidc/callback
  3. Configure environment variables:
    DOMAIN=your-domain.com                    # or PHX_HOST=your-domain.com
    OIDC_CLIENT_ID=your-client-id
    OIDC_BASE_URL=https://auth.example.com/application/o/your-app
    OIDC_CLIENT_SECRET=your-client-secret     # or use OIDC_CLIENT_SECRET_FILE
    

The OIDC_REDIRECT_URI is auto-generated as https://{DOMAIN}/auth/user/oidc/callback if not explicitly set.

⚙️ Configuration

  • Env vars: see .env.example

🏗️ Architecture

Tech Stack Overview:

  • Backend: Elixir + Phoenix + Ash Framework
  • Frontend: Phoenix LiveView + Tailwind CSS + DaisyUI
  • Database: PostgreSQL
  • Auth: AshAuthentication (OIDC + password)

Code Structure:

  • lib/accounts/ & lib/membership/ & lib/membership_fees/ & lib/mv/authorization/ — Ash resources and domains
  • lib/mv_web/ — Phoenix controllers, LiveViews, components
  • lib/mv/ — Shared helpers and business logic
  • assets/ — Tailwind, JavaScript, static files
  • test/ — All tests

📚 Full tech stack details: See CODE_GUIDELINES.md
📖 Implementation history: See docs/development-progress-log.md
🗄️ Database schema: See docs/database-schema-readme.md

🧑‍💻 Development

Common commands:

just run                      # Start full dev environment
just test                     # Run test suite
just lint                     # Code style checks
just audit                    # Security audits
just reset-database           # Reset local DB

📚 Full development guidelines: See CODE_GUIDELINES.md

📦 Production Deployment

Local Production Testing

For testing the production Docker build locally:

  1. Generate secrets:

    mix phx.gen.secret  # for SECRET_KEY_BASE
    mix phx.gen.secret  # for TOKEN_SIGNING_SECRET
    
  2. Create .env file:

    # Copy template and edit
    cp .env.example .env
    nano .env
    
  3. Start production environment:

    docker compose -f docker-compose.prod.yml up
    
  4. Database migrations run automatically on app start. For manual migration:

    docker compose -f docker-compose.prod.yml exec app /app/bin/mv eval "Mv.Release.migrate"
    
  5. Access the production app:

Note: The local production setup uses network_mode: host to share localhost with the development Rauthy instance. For real production deployment, configure an external OIDC provider and remove network_mode: host.

Real Production Deployment

For actual production deployment:

  1. Use an external OIDC provider (not the local Rauthy)
  2. Update docker-compose.prod.yml:
    • Remove network_mode: host
    • Set OIDC_BASE_URL to your production OIDC provider
    • Configure proper Docker networks
  3. Set up SSL/TLS (e.g., via reverse proxy like Nginx/Traefik)
  4. Use secure secrets management — All sensitive environment variables support a _FILE suffix for Docker secrets (e.g., SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base). See docker-compose.prod.yml for an example setup with Docker secrets.
  5. Configure database backups

🤝 Contributing

We welcome contributions!

  • Open issues and PRs in this repo
  • Please follow existing code style and conventions
  • Expect breaking changes while the project is in early development

📄 License

License: AGPLv3
See the LICENSE file for details.

📬 Contact