first commit
This commit is contained in:
465
README.md
Normal file
465
README.md
Normal file
@@ -0,0 +1,465 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user