# Mila
**Mila** β simple, usable, self-hostable membership management for small to mid-sized clubs.
[](https://drone.dev.local-it.cloud/local-it/mitgliederverwaltung)

## π§ Project Status
β οΈ **Early development** β not production-ready. 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 donβt need
* **Too expensive** β hidden fees, closed ecosystems, vendor lock-in
* **Too rigid** β no way to adapt fields, processes, or roles to your clubβs 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.**
## πΈ Screenshots

*This is how Mila might look in action.*
## π Features
- β
Manage member data with ease
- π§ Overview of membership fees & payment status
- β
Full-text search
- π§ Sorting & filtering
- π§ Roles & permissions (e.g. board, treasurer)
- β
Custom fields (flexible per club needs)
- β
SSO via OIDC (tested with Rauthy)
- π§ Self-service & online application
- π§ Accessibility, GDPR, usability improvements
- π§ Email sending
## π Quick Start (Development)
### Prerequisites
We recommend using **[asdf](https://asdf-vm.com/)** 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)
```bash
# 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
```bash
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`):
```fish
asdf completion fish > ~/.config/fish/completions/asdf.fish
set -gx PATH "$HOME/.asdf/shims" $PATH
```
*Bash example* (`~/.bash_profile` and `~/.bashrc`):
```bash
export PATH="${ASDF_DATA_DIR:-$HOME/.asdf}/shims:$PATH"
. <(asdf completion bash)
```
### Install project dependencies
```bash
git clone https://git.local-it.org/local-it/mitgliederverwaltung.git mila
cd mila
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:
```bash
cp .env.example .env
# Set OIDC_CLIENT_SECRET inside .env
```
2. Start everything (database, Mailcrab, Rauthy, app):
```bash
just run
```
3. Services will be available at:
- App:
- Mail UI:
- Postgres: `localhost:5000`
## π Testing SSO locally
Mila uses OIDC for Single Sign-On. In development, a local **Rauthy** instance is provided.
1. `just run`
2. go to [localhost:8080](http://localhost:8080), go to the Admin area
3. Login with "admin@localhost" and password from `BOOTSTRAP_ADMIN_PASSWORD_PLAIN` in docker-compose.yml
4. add client from the admin panel
- Client ID: mv
- redirect uris: http://localhost:4000/auth/user/rauthy/callback
- Authorization Flows: authorization_code
- allowed origins: http://localhost:4000
- access/id token algortihm: RS256 (EDDSA did not work for me, found just few infos in the ashauthentication docs)
5. copy client secret to `.env` file
6. abort and run `just run` again
Now you can log in to Mila via OIDC!
## βοΈ Configuration
- **Env vars:** see `.env.example`
- `OIDC_CLIENT_SECRET` β secret for your OIDC client
- Database defaults (Docker Compose):
- Host: `localhost`
- Port: `5000`
- User/pass: `postgres` / `postgres`
- DB: `mila_dev`
## ποΈ 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/` β Ash resources and domains
- `lib/mv_web/` β Phoenix controllers, LiveViews, components
- `assets/` β Tailwind, JavaScript, static files
π **Full tech stack details:** See [`CODE_GUIDELINES.md`](CODE_GUIDELINES.md)
π **Implementation history:** See [`docs/development-progress-log.md`](docs/development-progress-log.md)
ποΈ **Database schema:** See [`docs/database-schema-readme.md`](docs/database-schema-readme.md)
## π§βπ» Development
**Common commands:**
```bash
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`](CODE_GUIDELINES.md)
## π¦ Production Deployment
### Local Production Testing
For testing the production Docker build locally:
1. **Generate secrets:**
```bash
mix phx.gen.secret # for SECRET_KEY_BASE
mix phx.gen.secret # for TOKEN_SIGNING_SECRET
```
2. **Create `.env` file:**
```bash
# Copy template and edit
cp .env.example .env
nano .env
# Required variables:
SECRET_KEY_BASE=
TOKEN_SIGNING_SECRET=
PHX_HOST=localhost
# Optional (have defaults in docker-compose.prod.yml):
# OIDC_CLIENT_ID=mv
# OIDC_BASE_URL=http://localhost:8080/auth/v1
# OIDC_REDIRECT_URI=http://localhost:4001/auth/user/rauthy/callback
# OIDC_CLIENT_SECRET=
# Alternative: Use _FILE variables for Docker secrets (takes priority over regular vars):
# SECRET_KEY_BASE_FILE=/run/secrets/secret_key_base
# TOKEN_SIGNING_SECRET_FILE=/run/secrets/token_signing_secret
# OIDC_CLIENT_SECRET_FILE=/run/secrets/oidc_client_secret
# DATABASE_URL_FILE=/run/secrets/database_url
# DATABASE_PASSWORD_FILE=/run/secrets/database_password
```
3. **Start development environment** (for Rauthy):
```bash
docker compose up -d
```
4. **Start production environment:**
```bash
docker compose -f docker-compose.prod.yml up
```
5. **Run database migrations:**
```bash
docker compose -f docker-compose.prod.yml exec app /app/bin/mv eval "Mv.Release.migrate"
```
6. **Access the production app:**
- Production App: http://localhost:4001
- Uses same Rauthy instance as dev (localhost:8080)
**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](LICENSE) file for details.
## π¬ Contact
- Issues: [GitLab Issues](https://git.local-it.org/local-it/mitgliederverwaltung/-/issues)
- Community links: coming soon.