A comprehensive IT infrastructure management platform that provides centralized user management, VPN access, Linux account provisioning, and LDAP-based authentication.
- Centralized User Management: Web-based portal for managing users, profiles, and access
- LDAP Integration: OpenLDAP directory service for Linux authentication with SSHA password hashing
- VPN Access: OpenVPN server with OTP (Google Authenticator) support and profile URL import
- Linux Account Provisioning: Automated creation of Linux accounts with home directories
- Group Management: LDAP-based group management with member synchronization
- Role-Based Access Control: Admin, group admin, and regular user roles
- User Lifecycle Management: Automatic deactivation and archival of expired accounts
- Email Notifications: Bulk email system for active users
- IP Whitelisting: Caddy-based access control for network security
- Frontend: SvelteKit application with SSR (port 3000 internally)
- Backend: Django + Django Ninja REST API (port 8080 internally)
- Database: PostgreSQL 13
- LDAP: OpenLDAP server for Linux authentication (port 636)
- VPN: OpenVPN server with OTP authentication (port 1194/udp)
- Reverse Proxy: Caddy server handling HTTPS and access control
- Task Queue: Celery with RabbitMQ for async tasks
- Backend: Python, Django 4.2, Django Ninja, Celery
- Frontend: SvelteKit, Flowbite, Tailwind CSS
- Database: PostgreSQL 13
- Directory: OpenLDAP with python-ldap
- VPN: OpenVPN with openvpn-auth-ldap and PAM OTP
- Reverse Proxy: Caddy 2
- Message Queue: RabbitMQ
- Docker and Docker Compose
- Linux host with
/dev/net/tunsupport (for VPN)
-
Clone the repository
git clone <repository-url> cd dari
-
Configure environment variables
cp .env.example .env # Edit .env with your configurationRequired variables:
SECRET_KEY: Django secret key (generate withopenssl rand -base64 32)LDAP_ADMIN_PASSWORD: LDAP admin passwordLDAP_DOMAIN: LDAP domain (e.g., "dari" becomes dc=dari)SITE_DOMAIN: Domain for the service (e.g., vpn.example.com)DB_USER,DB_PASSWORD,DB_NAME: PostgreSQL credentialsRABBITMQ_DEFAULT_USER,RABBITMQ_DEFAULT_PASS: RabbitMQ credentials
-
Start services
Development mode (with hot-reload):
docker compose -f compose-dev.yml up --build
Production mode:
docker compose up -d --build
-
Access the application
- Open your browser to
http://localhost:8080(dev) orhttp://<SITE_DOMAIN>(production) - Register the first user (automatically becomes admin)
- Complete initial setup at
/init
- Open your browser to
-
Regular Users
- Authenticate via LDAP
- Have Linux accounts with home directories
- Can access VPN with OTP
- Passwords stored as SSHA hashes in LDAP
-
Guest Users
- Authenticate via Django
- No Linux accounts
- Temporary access with expiration dates
- Usernames start with "guest"
-
Administrators
- Full system access
- Manage users, groups, and settings
- Can reset passwords and configure system
-
Group Admins
- Manage specific LDAP groups
- Limited administrative privileges
- User registers at
/registerwith username, password, and name - Backend atomically creates:
- Django User + Profile + LinuxInfo
- LDAP entry with SSHA-hashed password
- Home directory with proper ownership
- First user automatically becomes superuser
-
Enable OTP
- Navigate to VPN page in portal
- Generate QR code
- Scan with Google Authenticator, FreeOTP, or Microsoft Authenticator
-
Download OpenVPN Profile
- Click "Download Profile" button, or
- Use profile import URL in OpenVPN Connect app
-
Connect to VPN
- Username: Your Linux username
- Password: Your LDAP password + OTP code (e.g.,
mypassword123456)
- OpenVPN uses two-factor authentication:
- LDAP password: Validated via openvpn-auth-ldap plugin
- OTP code: Validated via PAM with Google Authenticator
- Client profile is dynamically generated using
SITE_DOMAIN - Profile available at
/api/vpn/profilefor URL import
# Enter backend container
docker compose exec backend bash
# Run migrations
python manage.py makemigrations
python manage.py migrate
# Create superuser
python manage.py createsuperuser
# Django shell
python manage.py shell
# Check Celery tasks
celery -A backend inspect active# Enter frontend container (dev mode)
docker compose -f compose-dev.yml exec frontend sh
# Install dependencies
cd /app && pnpm install
# Build for production
pnpm run build# Access PostgreSQL
docker compose exec db psql -U dari -d dari
# Backup database
docker compose exec db pg_dump -U dari dari > backup.sql
# Restore database
docker compose exec -T db psql -U dari dari < backup.sql# Search users
docker compose exec ldap ldapsearch -x -H ldap://localhost -b "ou=users,dc=dari" -D "cn=admin,dc=dari" -w <admin_password>
# Search groups
docker compose exec ldap ldapsearch -x -H ldap://localhost -b "ou=groups,dc=dari" -D "cn=admin,dc=dari" -w <admin_password>Key endpoints in /api/:
POST /register- Register new user with Linux/LDAP accountPOST /login- Authenticate via LDAP (regular) or Django (guest)POST /password- Change user's LDAP passwordPOST /qr- Generate Google Authenticator QR for VPN OTPGET /vpn/profile- Download OpenVPN client profile (public)GET /me- Get current user infoGET /users- List users (admin)PATCH /user- Update user attributes (admin)POST /guest- Create guest user (admin)GET /groups- List LDAP groupsPOST /group- Create LDAP group (admin)PUT /group- Update LDAP groupPOST /emailsend- Send bulk email (admin)
- Base DN:
dc=<LDAP_DOMAIN> - Users OU:
ou=users,dc=<LDAP_DOMAIN> - Groups OU:
ou=groups,dc=<LDAP_DOMAIN> - Admin DN:
cn=admin,dc=<LDAP_DOMAIN>
- Production:
/mnt/dari-home/<username> - Development:
./dari-home/<username> - Created from
/etc/skeltemplate - Proper UID/GID ownership applied automatically
Runs daily at midnight:
remove_users()- Archives and deletes expired users after 6 monthsdeactivate_users()- Marks users inactive after expiration date
- All passwords stored securely (LDAP: SSHA hash, Django: PBKDF2)
- IP whitelisting via Caddy reverse proxy
- TLS support for LDAP (port 636)
- Two-factor authentication for VPN
- CSRF protection on all API endpoints
- Session-based authentication with secure cookies
Production volumes in ./db/:
postgres_data/- PostgreSQL databaseldap_data/,ldap_config/,ldap_certs/- LDAP directory, config, and auto-generated TLS certificatescaddy_data/,caddy_config/- Caddy certificates and configvpn_easy_rsa/- VPN PKI and auto-generated certificatesovpn/- Generated OpenVPN client profileqr/- VPN OTP secretsip_addresses- Server IP whitelist file
All certificates (LDAP, VPN) are auto-generated on first initialization.
# View all logs
docker compose logs -f
# View specific service logs
docker compose logs -f backend
docker compose logs -f vpn
docker compose logs -f ldap-
LDAP connection failed
- Check LDAP container is running:
docker compose ps ldap - Verify LDAP_ADMIN_PASSWORD in .env
- Check LDAP logs:
docker compose logs ldap
- Check LDAP container is running:
-
VPN connection failed
- Ensure OTP is enabled in user profile
- Verify password + OTP format:
<password><6-digit-code> - Check VPN logs:
docker compose logs vpn
-
Database migration errors
- Run migrations manually:
docker compose exec backend python manage.py migrate - Check database is accessible:
docker compose exec db psql -U dari -d dari
- Run migrations manually:
MIT License
Copyright (c) 2025 Jeongbin Park
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.