466 lines
18 KiB
Markdown
466 lines
18 KiB
Markdown
# Organization Stack
|
|
|
|
A self-hosted collaboration and authentication platform featuring Single Sign-On (SSO), Two-Factor Authentication (2FA), centralized user management, Git hosting, and wiki collaboration.
|
|
|
|
## Overview
|
|
|
|
This project provides a complete, production-ready stack for small to medium organizations seeking self-hosted alternatives to cloud services. All components communicate through modern authentication standards (LDAP, OIDC, Forward-Auth) providing seamless single sign-on across all services.
|
|
|
|
### Components
|
|
|
|
- **[lldap](https://github.com/lldap/lldap)** - Lightweight LDAP directory for centralized user and group management
|
|
- **[Authelia](https://www.authelia.com/)** - SSO authentication server with 2FA/TOTP support, OIDC provider, and forward-auth endpoint
|
|
- **[Gitea](https://gitea.io/)** - Self-hosted Git service with web UI (authenticated via OIDC)
|
|
- **[JSPWiki](https://jspwiki.apache.org/)** - Collaborative wiki platform (authenticated via Forward-Auth)
|
|
- **Registration Service** - User self-provisioning with admin approval (FastAPI + SQLite)
|
|
- **[Caddy](https://caddyserver.com/)** - Reverse proxy with automatic HTTPS via Let's Encrypt
|
|
|
|
### Key Features
|
|
|
|
- **Single Sign-On (SSO)** - One set of credentials for all services
|
|
- **Two-Factor Authentication** - TOTP (Google Authenticator, Authy, etc.) support
|
|
- **Automatic HTTPS** - Let's Encrypt certificates managed by Caddy
|
|
- **File-Based Secrets** - Secure secret management following Docker best practices
|
|
- **One-Command Deployment** - Automated setup script handles everything
|
|
- **Zero Manual Configuration** - Template-based config generation from `.env`
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- **Remote Server**: Linux server with Docker and Docker Compose v2 installed
|
|
- **Local Machine**: SSH access to remote server, rsync installed
|
|
- **Domain**: Domain name with DNS pointing to your server (or `/etc/hosts` for testing)
|
|
|
|
### Installation
|
|
|
|
> **Note**: For production deployments with multiple administrators, see [MULTI_ADMIN_SETUP.md](MULTI_ADMIN_SETUP.md) for system-wide installation with proper permissions.
|
|
|
|
1. **Clone the repository**
|
|
```bash
|
|
git clone https://github.com/yourorg/org-stack.git
|
|
cd org-stack
|
|
```
|
|
|
|
2. **Configure environment**
|
|
```bash
|
|
cp .env.example .env
|
|
nano .env # Edit BASE_DOMAIN, REMOTE_USER, REMOTE_HOST
|
|
```
|
|
|
|
Required changes in `.env`:
|
|
- `BASE_DOMAIN=example.com` → your actual domain
|
|
- `REMOTE_USER=user` → your SSH username (or `deploy` for multi-admin)
|
|
- `REMOTE_HOST=example.com` → your server hostname/IP
|
|
- `REMOTE_PATH=/opt/org-stack` → optional, for system-wide installation
|
|
|
|
3. **Deploy**
|
|
```bash
|
|
./deploy.sh
|
|
```
|
|
|
|
The deploy script will:
|
|
- Generate all required secrets automatically
|
|
- Create configuration files from templates
|
|
- Sync files to your remote server via rsync
|
|
- Start all Docker containers
|
|
|
|
4. **Access services**
|
|
- **lldap**: https://ldap.yourdomain.com (create users here first)
|
|
- **Authelia**: https://auth.yourdomain.com
|
|
- **Gitea**: https://git.yourdomain.com
|
|
- **Wiki**: https://wiki.yourdomain.com
|
|
- **Registration**: https://register.yourdomain.com (public user registration)
|
|
|
|
### First-Time Setup
|
|
|
|
After deployment, complete these steps:
|
|
|
|
1. **Create users in lldap**
|
|
- Access https://ldap.yourdomain.com
|
|
- Login with admin credentials (shown by deploy.sh)
|
|
- Create user accounts and assign to `lldap_admin` group for admin privileges
|
|
|
|
2. **Setup Gitea**
|
|
- Access https://git.yourdomain.com
|
|
- Complete the installation wizard (use defaults)
|
|
- Go to Site Admin → Authentication Sources → Add Authentication Source
|
|
- Type: `OAuth2`
|
|
- Authentication Name: `authelia` ⚠️ **IMPORTANT: Must be lowercase!**
|
|
- Provider: `OpenID Connect`
|
|
- Client ID: `gitea`
|
|
- Client Secret: (shown by deploy.sh)
|
|
- OpenID Connect Auto Discovery URL: `http://authelia:9091/.well-known/openid-configuration`
|
|
- Logout and test "Sign in with OpenID Connect"
|
|
|
|
3. **Test the wiki**
|
|
- Access https://wiki.yourdomain.com
|
|
- You'll be redirected to Authelia for login
|
|
- After authentication, you'll have admin access if you're in the `lldap_admin` group
|
|
|
|
4. **Enable user self-registration (optional)**
|
|
- Users can submit registration requests at https://register.yourdomain.com
|
|
- Admins review requests at https://register.yourdomain.com/admin (requires Authelia login)
|
|
- Admin dashboard shows:
|
|
- **Pending requests**: Approve or reject with optional reason
|
|
- **Audit log**: Historical record of all approval/rejection decisions
|
|
- When approved:
|
|
- User is automatically created in lldap with random password
|
|
- User receives email with credentials (if SMTP configured in .env)
|
|
- Request is moved to audit log
|
|
- **User management**: After approval, manage users directly in lldap (single source of truth)
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
│ Internet / Users │
|
|
└──────────────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
┌─────────▼──────────┐
|
|
│ Caddy (HTTPS) │ ← Automatic Let's Encrypt
|
|
│ Reverse Proxy │
|
|
└──────────┬─────────┘
|
|
│
|
|
┌───────────────────┼───────────────────┐
|
|
│ │ │
|
|
┌───────▼────────┐ ┌──────▼────────┐ ┌──────▼────────┐
|
|
│ Gitea (Git) │ │ JSPWiki (Wiki)│ │ lldap (Admin)│
|
|
│ via OIDC ────┼──┤ via Fwd-Auth ─┼──┤ via Fwd-Auth ─┼──┐
|
|
└────────────────┘ └───────────────┘ └───────────────┘ │
|
|
│
|
|
┌────────────────────────────────────┘
|
|
│
|
|
┌────────▼─────────┐
|
|
│ Authelia │ ← SSO/2FA/OIDC/Forward-Auth
|
|
│ (Auth Server) │
|
|
└────────┬─────────┘
|
|
│
|
|
┌────────▼─────────┐
|
|
│ lldap │ ← User Database (LDAP)
|
|
└──────────────────┘
|
|
```
|
|
|
|
### Authentication Flow
|
|
|
|
**OIDC Flow (Gitea)**:
|
|
1. User accesses Gitea → redirected to Authelia
|
|
2. Authelia validates credentials against lldap via LDAP
|
|
3. Authelia enforces 2FA (TOTP)
|
|
4. Authelia issues OIDC tokens
|
|
5. User redirected back to Gitea, logged in
|
|
|
|
**Forward-Auth Flow (Wiki, lldap)**:
|
|
1. User accesses Wiki → Caddy forwards auth request to Authelia
|
|
2. Authelia validates session (or prompts login + 2FA)
|
|
3. Authelia returns `Remote-User` header
|
|
4. Caddy forwards request to Wiki with authenticated user header
|
|
5. Wiki trusts the `Remote-User` header (container authentication)
|
|
|
|
For detailed architecture documentation, see [ARCHITECTURE.md](./ARCHITECTURE.md).
|
|
|
|
## Configuration
|
|
|
|
All configuration is managed through a single `.env` file. The deployment script generates service-specific configs from templates.
|
|
|
|
### Key Configuration Options
|
|
|
|
```bash
|
|
# Domain Configuration
|
|
BASE_DOMAIN=example.com # Your domain
|
|
GITEA_SUBDOMAIN=git # Creates git.example.com
|
|
WIKI_SUBDOMAIN=wiki # Creates wiki.example.com
|
|
AUTH_SUBDOMAIN=auth # Creates auth.example.com
|
|
LLDAP_SUBDOMAIN=ldap # Creates ldap.example.com
|
|
|
|
# TLS Mode
|
|
USE_SELF_SIGNED_CERTS=false # false=Let's Encrypt, true=self-signed
|
|
|
|
# Authentication
|
|
REQUIRE_2FA=true # Require TOTP for all services
|
|
|
|
# Advanced
|
|
SESSION_EXPIRATION=1h # How long sessions last
|
|
MAX_RETRIES=3 # Failed login attempts before ban
|
|
```
|
|
|
|
See `.env.example` for complete documentation of all options.
|
|
|
|
### SMTP Email Notifications
|
|
|
|
To enable email notifications for password resets, 2FA codes, and registration approvals:
|
|
|
|
1. Edit `.env` and configure SMTP settings:
|
|
```bash
|
|
SMTP_ENABLED=true
|
|
SMTP_HOST="smtp.gmail.com"
|
|
SMTP_PORT=587
|
|
SMTP_USER="your-email@gmail.com"
|
|
SMTP_PASSWORD='your-app-password' # Use quotes for special characters
|
|
SMTP_FROM="noreply@yourdomain.com"
|
|
```
|
|
|
|
2. Deploy changes:
|
|
```bash
|
|
./deploy.sh
|
|
```
|
|
|
|
See [SMTP_SETUP.md](SMTP_SETUP.md) for detailed configuration examples and troubleshooting.
|
|
|
|
## Management
|
|
|
|
The `manage.sh` script provides common operations:
|
|
|
|
```bash
|
|
# View logs
|
|
./manage.sh logs # All services
|
|
./manage.sh logs authelia # Specific service
|
|
|
|
# Restart services
|
|
./manage.sh restart
|
|
|
|
# Update to latest images
|
|
./manage.sh update
|
|
|
|
# Backup data volumes
|
|
./manage.sh backup
|
|
|
|
# Restore from backup
|
|
./manage.sh restore backup-YYYYMMDD-HHMMSS.tar.gz
|
|
|
|
# Complete reset (DESTRUCTIVE - deletes all data)
|
|
./manage.sh reset
|
|
|
|
# Check service status
|
|
./manage.sh status
|
|
```
|
|
|
|
## Security Features
|
|
|
|
### Secrets Management
|
|
All secrets are stored as individual files (not environment variables) following Docker security best practices:
|
|
- Mounted read-only to containers
|
|
- Not visible in `docker inspect` or process listings
|
|
- Individual file permissions (600)
|
|
- Never committed to git (secrets/ in .gitignore)
|
|
|
|
### Authentication Layers
|
|
1. **Centralized User Database**: Single source of truth in lldap
|
|
2. **SSO Authentication**: Authelia validates all login attempts
|
|
3. **Two-Factor Authentication**: TOTP enforcement for all services
|
|
4. **Session Management**: Configurable expiration and inactivity timeouts
|
|
5. **Rate Limiting**: Brute-force protection with automatic bans
|
|
|
|
### Network Security
|
|
|
|
**Hardened Configuration:**
|
|
- **Zero Direct Access**: No service ports exposed except through Caddy
|
|
- **Exposed Ports**: Only 80/443 (HTTP/HTTPS) and 2222 (Git SSH)
|
|
- **Internal Communication**: All services use Docker network hostnames
|
|
- **Authentication Required**: Every service requires Authelia login (except public registration form)
|
|
- **TLS Termination**: Caddy handles all HTTPS with automatic certificate management
|
|
- **Network Isolation**: Services isolated on internal Docker bridge network
|
|
|
|
**Port Summary:**
|
|
- `80/443` → Caddy (reverse proxy) → All web services
|
|
- `2222` → Gitea SSH (for Git operations only)
|
|
- All other services accessible ONLY via Caddy with Authelia authentication
|
|
|
|
## Protocols & Technologies
|
|
|
|
This project demonstrates integration of several authentication protocols:
|
|
|
|
### LDAP (Lightweight Directory Access Protocol)
|
|
- **Implementation**: lldap
|
|
- **RFC**: [RFC 4511](https://tools.ietf.org/html/rfc4511)
|
|
- **Used for**: Centralized user/group storage, credential verification
|
|
- **Resources**:
|
|
- [lldap GitHub](https://github.com/lldap/lldap)
|
|
- [LDAP Wikipedia](https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol)
|
|
|
|
### OIDC (OpenID Connect)
|
|
- **Implementation**: Authelia (provider), Gitea (client)
|
|
- **Spec**: [OpenID Connect Core 1.0](https://openid.net/specs/openid-connect-core-1_0.html)
|
|
- **Used for**: Gitea SSO authentication
|
|
- **Resources**:
|
|
- [OpenID Connect Explained](https://connect2id.com/learn/openid-connect)
|
|
- [Authelia OIDC Docs](https://www.authelia.com/integration/openid-connect/introduction/)
|
|
|
|
### Forward-Auth
|
|
- **Implementation**: Authelia (endpoint), Caddy (proxy)
|
|
- **Used for**: Wiki and lldap authentication via trusted headers
|
|
- **How it works**: Proxy delegates authentication to external service before forwarding requests
|
|
- **Resources**:
|
|
- [Authelia Forward-Auth Docs](https://www.authelia.com/integration/proxies/fowarded-headers/)
|
|
- [Caddy forward_auth Directive](https://caddyserver.com/docs/caddyfile/directives/forward_auth)
|
|
|
|
### TOTP (Time-Based One-Time Password)
|
|
- **Implementation**: Authelia, compatible with Google Authenticator/Authy
|
|
- **RFC**: [RFC 6238](https://tools.ietf.org/html/rfc6238)
|
|
- **Used for**: Two-factor authentication
|
|
- **Resources**:
|
|
- [TOTP Wikipedia](https://en.wikipedia.org/wiki/Time-based_One-Time_Password)
|
|
- [Authelia 2FA Docs](https://www.authelia.com/overview/authentication/one-time-password/)
|
|
|
|
## Troubleshooting
|
|
|
|
### Check notifications (2FA codes, password resets)
|
|
```bash
|
|
ssh user@server 'cd ~/org-stack && docker compose exec authelia cat /data/notification.txt'
|
|
```
|
|
|
|
Or use the manage script:
|
|
```bash
|
|
./manage.sh logs authelia | grep -A 20 "one-time code"
|
|
```
|
|
|
|
### Gitea OIDC not working
|
|
|
|
**Error: "invalid_request" or "redirect_uri does not match"**
|
|
- **Cause**: Authentication source name is case-sensitive
|
|
- **Solution**: Name must be exactly `authelia` (lowercase) in Gitea admin panel
|
|
- **Why**: Gitea uses the name in redirect URI: `/user/oauth2/{name}/callback`
|
|
|
|
**Other common issues:**
|
|
1. Verify OIDC configuration uses internal URL:
|
|
- Auto Discovery URL: `http://authelia:9091/.well-known/openid-configuration` (NOT https://)
|
|
2. Check Authelia logs: `./manage.sh logs authelia`
|
|
3. Verify client secret matches what deploy.sh showed
|
|
|
|
### Services showing 502 errors
|
|
1. Check if all containers are running: `./manage.sh status`
|
|
2. Check Authelia logs: `./manage.sh logs authelia`
|
|
3. Verify secrets are mounted: `ssh user@server 'ls -la ~/org-stack/secrets/authelia'`
|
|
|
|
### 2FA not working
|
|
1. Verify `REQUIRE_2FA=true` in `.env`
|
|
2. Redeploy: `./deploy.sh`
|
|
3. Check Authelia configuration: `cat authelia/configuration.yml | grep policy`
|
|
|
|
### Let's Encrypt certificate failures
|
|
1. Verify DNS points to your server: `dig yourdomain.com`
|
|
2. Verify ports 80 and 443 are accessible externally
|
|
3. Check Caddy logs: `./manage.sh logs caddy`
|
|
4. If testing, use self-signed: `USE_SELF_SIGNED_CERTS=true` in `.env`
|
|
|
|
## Backup & Recovery
|
|
|
|
### Backup
|
|
```bash
|
|
./manage.sh backup
|
|
```
|
|
|
|
Creates timestamped tarball of all Docker volumes in `backups/` directory.
|
|
|
|
### Restore
|
|
```bash
|
|
./manage.sh restore backups/backup-YYYYMMDD-HHMMSS.tar.gz
|
|
```
|
|
|
|
### What's Backed Up
|
|
- lldap database (all users and groups)
|
|
- Authelia data (sessions, 2FA registrations)
|
|
- Gitea data (all repositories)
|
|
- JSPWiki data (all wiki pages)
|
|
- Caddy data (TLS certificates)
|
|
|
|
**Note**: The `secrets/` directory is NOT backed up by design. Back it up separately and securely.
|
|
|
|
## Development
|
|
|
|
### Testing Changes Locally
|
|
```bash
|
|
# Use self-signed certs to avoid Let's Encrypt rate limits
|
|
echo "USE_SELF_SIGNED_CERTS=true" >> .env
|
|
|
|
# For local testing without DNS, add to /etc/hosts:
|
|
echo "127.0.0.1 git.example.com wiki.example.com auth.example.com ldap.example.com" | sudo tee -a /etc/hosts
|
|
|
|
# Deploy
|
|
./deploy.sh
|
|
```
|
|
|
|
### Project Structure
|
|
```
|
|
org-stack/
|
|
├── .env.example # Configuration template
|
|
├── deploy.sh # Automated deployment script
|
|
├── manage.sh # Management utilities
|
|
├── compose.yml # Docker Compose service definitions
|
|
├── Caddyfile.*.template # Caddy templates (prod/test)
|
|
├── authelia/
|
|
│ └── configuration.yml.template # Authelia config template
|
|
├── jspwiki/
|
|
│ ├── Dockerfile # Custom JSPWiki image
|
|
│ ├── RemoteUserFilter.java # Servlet filter for SSO
|
|
│ ├── ldap-sync.sh # LDAP user synchronization
|
|
│ ├── configure-web-xml.sh # web.xml modification for container auth
|
|
│ └── entrypoint.sh # Container startup script
|
|
├── jspwiki-custom.properties # JSPWiki config (container auth)
|
|
├── jspwiki.policy # JSPWiki security policy
|
|
└── secrets/ # Auto-generated secrets (gitignored)
|
|
├── lldap/
|
|
│ ├── JWT_SECRET
|
|
│ └── LDAP_USER_PASS
|
|
└── authelia/
|
|
├── JWT_SECRET
|
|
├── SESSION_SECRET
|
|
├── STORAGE_ENCRYPTION_KEY
|
|
├── OIDC_HMAC_SECRET
|
|
└── OIDC_PRIVATE_KEY
|
|
```
|
|
|
|
## Production Recommendations
|
|
|
|
### Network Security
|
|
1. **Firewall Rules**:
|
|
```bash
|
|
# Allow only necessary ports
|
|
ufw allow 80/tcp # HTTP (redirects to HTTPS)
|
|
ufw allow 443/tcp # HTTPS
|
|
ufw allow 2222/tcp # Git SSH (optional, only if using Git SSH)
|
|
ufw allow 22/tcp # SSH for server management
|
|
ufw enable
|
|
```
|
|
2. **Port Verification**: Only 80, 443, and 2222 should be accessible externally
|
|
3. **DNS Configuration**: Ensure A records point to your server for all subdomains
|
|
|
|
### Operational Security
|
|
4. **Backups**: Schedule regular backups with `./manage.sh backup`
|
|
5. **Monitoring**: Set up monitoring for container health and authentication failures
|
|
6. **Updates**: Regularly update with `./manage.sh update`
|
|
7. **Secrets Rotation**: Periodically regenerate secrets and redeploy
|
|
8. **SMTP**: Configure real email notifier in `.env` (replace file-based logging)
|
|
|
|
### Performance
|
|
9. **Database**: Consider PostgreSQL instead of SQLite for Gitea in high-traffic scenarios
|
|
10. **Rate Limiting**: Configure Caddy rate limiting for public endpoints
|
|
|
|
## Contributing
|
|
|
|
Contributions welcome! Please:
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Submit a pull request with clear description
|
|
|
|
## License
|
|
|
|
MIT License - see LICENSE file for details
|
|
|
|
## Acknowledgments
|
|
|
|
- **lldap**: Nitnelave and contributors
|
|
- **Authelia**: Authelia team
|
|
- **Gitea**: Gitea maintainers
|
|
- **JSPWiki**: Apache JSPWiki project
|
|
- **Caddy**: Caddy team
|
|
|
|
This project demonstrates integration of these excellent open-source tools into a cohesive authentication platform.
|
|
|
|
## Support
|
|
|
|
- **Issues**: [GitHub Issues](https://github.com/yourorg/org-stack/issues)
|
|
- **Discussions**: [GitHub Discussions](https://github.com/yourorg/org-stack/discussions)
|
|
- **Authelia Support**: [Authelia Discord](https://discord.authelia.com)
|
|
- **lldap Support**: [lldap Discussions](https://github.com/lldap/lldap/discussions)
|