diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6f3a24c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.tar.gz
+*_bak.tar.gz
diff --git a/README.md b/README.md
index 59d8299..845cd3a 100644
--- a/README.md
+++ b/README.md
@@ -1,149 +1,227 @@
# b0esche.cloud
-A self-hosted, SaaS-style document platform with Go backend and Flutter web frontend.
+A self-hosted, SaaS-style cloud storage and document platform with a Go backend and Flutter web frontend.
+
+π **Live:** [b0esche.cloud](https://b0esche.cloud)
+
+## Architecture
+
+```
+βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
+β Flutter Web ββββββΆβ Go Backend ββββββΆβ PostgreSQL β
+β (b0esche_cloud)β β (go_cloud) β β β
+βββββββββββββββββββ ββββββββββ¬βββββββββ βββββββββββββββββββ
+ β
+ ββββββββββββββΌβββββββββββββ
+ βΌ βΌ βΌ
+ ββββββββββββ ββββββββββββ ββββββββββββ
+ βNextcloud β βCollabora β β Traefik β
+ β(Storage) β β (Office) β β (Proxy) β
+ ββββββββββββ ββββββββββββ ββββββββββββ
+```
## Project Structure
-- `go_cloud/`: Go backend (control plane) with REST API
-- `b0esche_cloud/`: Flutter web frontend with BLoC architecture
-- Supporting services: Nextcloud (storage), Collabora (editing), PostgreSQL (database)
+```
+b0esche_cloud/
+βββ b0esche_cloud/ # Flutter web frontend
+β βββ lib/
+β β βββ blocs/ # BLoC state management
+β β βββ models/ # Data models
+β β βββ pages/ # UI pages
+β β βββ repositories/ # Data repositories
+β β βββ services/ # API services
+β β βββ theme/ # App theming
+β β βββ viewmodels/ # View models
+β β βββ widgets/ # Reusable widgets
+β βββ web/ # Web assets
+βββ go_cloud/ # Go backend
+β βββ cmd/api/ # Main entry point
+β βββ internal/
+β β βββ auth/ # Authentication (OIDC, Passkeys)
+β β βββ files/ # File management
+β β βββ org/ # Organization management
+β β βββ storage/ # Nextcloud/WebDAV integration
+β β βββ http/ # HTTP handlers & WOPI
+β β βββ ...
+β βββ migrations/ # Database migrations
+β βββ pkg/jwt/ # JWT utilities
+βββ scripts/ # Deployment & operations scripts
+βββ docs/ # Documentation
+ βββ AUTH.md # Authentication system docs
+```
+
+## Features
+
+- π **Authentication**: OIDC via Nextcloud + WebAuthn Passkeys
+- π **File Management**: Upload, download, organize files
+- π₯ **Organizations**: Multi-tenant with roles (Owner, Admin, Member)
+- π **Document Viewing**: PDF viewer, Office document preview
+- π **Real-time Sync**: Nextcloud/WebDAV backend storage
+- π **Auto-deployment**: Daily 3AM deployments via GitLab webhooks
## Prerequisites
- Go 1.21+
- Flutter 3.10+
-- Docker and Docker Compose
-- PostgreSQL (or Docker)
-- Nextcloud instance
-- Collabora Online instance
+- Docker & Docker Compose
+- PostgreSQL 15+
-## Local Development Setup
+## Local Development
-### 1. Start Supporting Services
-
-Use Docker Compose to start PostgreSQL, Nextcloud, and Collabora:
+### Quick Start
```bash
-docker-compose up -d db nextcloud collabora
+# Start everything
+./scripts/dev-all.sh
```
-### 2. Backend Setup
+### Manual Setup
+**Backend:**
```bash
cd go_cloud
cp .env.example .env
-# Edit .env with your configuration (DB URL, Nextcloud URL, etc.)
+# Edit .env with your configuration
go run ./cmd/api
```
-Or use the provided script:
-
-```bash
-./scripts/dev-backend.sh
-```
-
-### 3. Frontend Setup
-
+**Frontend:**
```bash
cd b0esche_cloud
flutter pub get
flutter run -d chrome
```
-Or use the script:
-
-```bash
-./scripts/dev-frontend.sh
-```
-
-### 4. Full Development Environment
-
-To start everything:
-
-```bash
-./scripts/dev-all.sh
-```
-
-This will bring up all services, backend, and frontend.
-
## Configuration
-### Backend (.env)
+### Backend Environment Variables
-Copy `go_cloud/.env.example` to `go_cloud/.env` and fill in:
+| Variable | Description |
+|----------|-------------|
+| `SERVER_ADDR` | Server address (default: `:8080`) |
+| `DATABASE_URL` | PostgreSQL connection string |
+| `JWT_SECRET` | Secret for JWT signing |
+| `OIDC_ISSUER_URL` | OIDC provider URL |
+| `OIDC_CLIENT_ID` | OIDC client ID |
+| `OIDC_CLIENT_SECRET` | OIDC client secret |
+| `NEXTCLOUD_URL` | Nextcloud instance URL |
+| `NEXTCLOUD_USERNAME` | Nextcloud admin username |
+| `NEXTCLOUD_PASSWORD` | Nextcloud admin password |
+| `COLLABORA_URL` | Collabora Online URL |
-- `DATABASE_URL`: PostgreSQL connection string
-- `JWT_SECRET`: Random secret for JWT signing
-- `OIDC_*`: OIDC provider settings
-- `NEXTCLOUD_*`: Nextcloud API settings
-- `COLLABORA_*`: Collabora settings
+## Production Deployment
-### Frontend
+The project runs on a VPS with Docker containers behind Traefik reverse proxy.
-The frontend uses build-time environment variables for API base URL. For dev, it's hardcoded in `ApiClient` constructor.
+### Services & Domains
-For production builds, update accordingly.
+| Domain | Service |
+|--------|---------|
+| `www.b0esche.cloud` | Flutter Web (Nginx) |
+| `go.b0esche.cloud` | Go API Backend |
+| `storage.b0esche.cloud` | Nextcloud (Storage + OIDC) |
+| `of.b0esche.cloud` | Collabora Online (Office) |
-## Running Tests
+### Server Directory Structure
-### Backend
-
-```bash
-cd go_cloud
-go test ./...
+```
+/opt/
+βββ traefik/ # Reverse proxy + SSL
+βββ go/ # Go backend + PostgreSQL
+βββ flutter/ # Flutter web build + Nginx
+βββ scripts/ # Operations scripts
+βββ auto-deploy/ # Auto-deployment workspace
```
-### Frontend
+### Server Scripts
+
+| Script | Description |
+|--------|-------------|
+| `auto-deploy.sh` | Daily automated deployment (runs at 3AM) |
+| `deploy-now.sh` | Trigger immediate deployment |
+| `backup.sh` | Full backup (DB, configs, volumes) |
+| `monitor.sh` | Health monitoring & alerts |
+| `webhook-server.py` | GitLab webhook receiver |
+
+### Deployment Commands
```bash
-cd b0esche_cloud
-flutter test
+# Trigger immediate deploy
+ssh b0esche-cloud '/opt/scripts/deploy-now.sh'
+
+# Check backend logs
+ssh b0esche-cloud 'docker logs go-backend -f'
+
+# Check service status
+ssh b0esche-cloud 'docker ps --format "table {{.Names}}\t{{.Status}}"'
+
+# Health checks
+curl -s https://go.b0esche.cloud/health
+curl -s https://www.b0esche.cloud | grep -o '
.*'
```
-## Building for Production
-
-### Backend
+### Starting Services (Manual)
```bash
-cd go_cloud
-go build -o bin/api ./cmd/api
-```
-
-### Frontend
-
-```bash
-cd b0esche_cloud
-flutter build web
+# Start all services in order
+ssh b0esche-cloud 'cd /opt/traefik && docker-compose up -d'
+ssh b0esche-cloud 'cd /opt/go && docker-compose up -d'
+ssh b0esche-cloud 'cd /opt/flutter && docker-compose up -d'
```
## Database Migrations
-Migrations are in `go_cloud/migrations/`.
-
-To apply:
+Migrations are in `go_cloud/migrations/`:
```bash
-# Dev
+cd go_cloud
go run github.com/pressly/goose/v3/cmd/goose@latest postgres "$DATABASE_URL" up
-
-# Production
-# Use your deployment tool to run the migration command
```
-## Backup Strategy
+## Backup & Recovery
-- **Database**: Regular PostgreSQL dumps of orgs, memberships, activities
-- **Files**: Nextcloud/S3 backups handled at storage layer
-- **Recovery**: Restore DB, then files; Go control plane is stateless
+Backups run daily and include:
+- PostgreSQL database dumps
+- Nextcloud database
+- Traefik certificates
+- Docker volumes
+- Configuration files
-## Contributing
+Backups are retained for 30 days.
-1. Clone the repo
-2. Follow local setup
-3. Make changes
-4. Run tests
-5. Submit PR
+```bash
+# Manual backup
+ssh b0esche-cloud '/opt/scripts/backup.sh'
+```
+
+## Testing
+
+```bash
+# Backend tests
+cd go_cloud && go test ./...
+
+# Frontend tests
+cd b0esche_cloud && flutter test
+```
+
+## Tech Stack
+
+| Component | Technology |
+|-----------|------------|
+| Frontend | Flutter Web, BLoC |
+| Backend | Go, Chi Router |
+| Database | PostgreSQL |
+| Storage | Nextcloud (WebDAV) |
+| Office | Collabora Online |
+| Auth | OIDC, WebAuthn |
+| Proxy | Traefik |
+| CI/CD | GitLab + Webhooks |
+
+## Documentation
+
+- [AUTH.md](docs/AUTH.md) - Complete authentication system documentation (Passkeys, OIDC, roles)
## License
-[License here]
+Private project - All rights reserved
diff --git a/b0esche_cloud_bak/b0esche_cloud_backup.tar.gz b/b0esche_cloud_bak/b0esche_cloud_backup.tar.gz
deleted file mode 100644
index 716f6a5..0000000
Binary files a/b0esche_cloud_bak/b0esche_cloud_backup.tar.gz and /dev/null differ
diff --git a/docs/AUTH.md b/docs/AUTH.md
new file mode 100644
index 0000000..6f130ec
--- /dev/null
+++ b/docs/AUTH.md
@@ -0,0 +1,279 @@
+# b0esche.cloud Authentication System
+
+This document describes the complete passkey-first authentication and authorization system for b0esche.cloud.
+
+## Overview
+
+b0esche.cloud implements a modern, secure, username-only, passkey-first authentication system with comprehensive admin functionality and recovery options.
+
+## Authentication Flow
+
+### Primary Authentication: Passkeys (WebAuthn)
+
+- **Username + Passkey Registration**: Users create an account with just a username and register a passkey
+- **Passkey-First Login**: Primary authentication method using WebAuthn/FIDO2 standards
+- **Device Support**: Works with Touch ID, Windows Hello, YubiKey, and other FIDO2 authenticators
+- **Multiple Passkeys**: Users can register multiple devices for redundancy
+
+### Fallback Options
+
+- **Optional Password**: Users can add a password as a fallback authentication method
+- **Recovery Codes**: 10 single-use recovery codes generated per user
+- **Admin Recovery**: Admins can assist with account recovery if needed
+
+## User Roles and Permissions
+
+### Role Hierarchy
+
+1. **superadmin** (Level 3): Full system access
+ - User management and role assignments
+ - Admin invitation system
+ - System configuration access
+ - All organization management
+
+2. **admin** (Level 2): Administrative access
+ - Organization management
+ - User role promotion (within their orgs)
+ - Activity monitoring
+ - File management across organizations
+
+3. **user** (Level 1): Standard user access
+ - Personal file management
+ - Organization membership
+ - Basic account settings
+
+## Bootstrap Process
+
+### Creating the First Administrator
+
+The system includes a bootstrap utility to create the first superadmin user securely:
+
+```bash
+# Interactive mode (recommended for production)
+./bin/bootstrap
+
+# Environment variable mode (recommended for automation)
+export BOOTSTRAP_ADMIN_USERNAME=admin
+export BOOTSTRAP_ADMIN_PASSWORD=secure_password_123
+./bin/bootstrap
+```
+
+#### Bootstrap Process
+
+1. **Check Existing Admin**: Verifies no superadmin user already exists
+2. **Secure Input**: Prompts for username and password (or reads from environment)
+3. **Password Security**: Enforces minimum 8-character passwords
+4. **Role Assignment**: Automatically assigns superadmin role
+5. **Secure Storage**: Passwords are bcrypt-hashed before storage
+
+#### Security Guidelines
+
+- **Immediate Action**: Log in immediately after bootstrap to register a passkey
+- **Passkey Priority**: Set up passkeys and consider removing the password
+- **Recovery Setup**: Generate recovery codes during first login
+- **Credential Rotation**: Never leave default credentials in production
+
+## API Endpoints
+
+### Authentication Endpoints
+
+```
+POST /auth/passkey/register/start
+POST /auth/passkey/register/verify
+POST /auth/passkey/login/start
+POST /auth/passkey/login/verify
+```
+
+### Device Management
+
+```
+GET /auth/passkey/devices # List user's passkeys
+POST /auth/passkey/devices/add # Add new passkey
+DELETE /auth/passkey/devices/{id} # Remove passkey
+```
+
+### Recovery System
+
+```
+POST /auth/recovery/codes/generate # Generate recovery codes
+POST /auth/recovery/codes/use # Use recovery code
+DELETE /auth/recovery/codes/revoke # Revoke all codes
+```
+
+### Admin Operations
+
+```
+GET /auth/admin/invitations # List invitations
+POST /auth/admin/invitations # Create invitation
+POST /auth/admin/invitations/accept # Accept invitation
+DELETE /auth/admin/invitations/{id} # Revoke invitation
+```
+
+### Password Fallback
+
+```
+POST /auth/password/add # Add password to account
+DELETE /auth/password/remove # Remove password from account
+```
+
+## Environment Configuration
+
+```bash
+# Server Configuration
+SERVER_ADDR=:8080
+DATABASE_URL=postgresql://user:pass@localhost/db
+
+# WebAuthn Configuration
+WEBAUTHN_RP_ID=www.b0esche.cloud
+WEBAUTHN_RP_NAME=b0esche.cloud
+WEBAUTHN_RP_ORIGIN=https://www.b0esche.cloud
+
+# Security Configuration
+JWT_SECRET=your_jwt_secret_key
+PASSKEY_TIMEOUT=300000
+RECOVERY_CODE_EXPIRY=86400
+MAX_RECOVERY_CODES=10
+```
+
+## Security Features
+
+### WebAuthn Security
+
+- **FIDO2/WebAuthn Compliant**: Full compliance with WebAuthn Level 2
+- **Origin Binding**: Credentials bound to specific domain
+- **Challenge-Response**: Cryptographic challenge verification
+- **Device Attestation**: Optional device verification
+- **Public Key Crypto**: Asymmetric cryptography with private keys never leaving devices
+
+### Account Security
+
+- **Rate Limiting**: Built-in protection against brute force attacks
+- **Session Management**: Secure HTTP-only sessions with configurable expiration
+- **Audit Logging**: Comprehensive logging of all authentication and admin actions
+- **Role-Based Access Control**: Hierarchical permission system
+
+### Data Protection
+
+- **Password Hashing**: bcrypt with automatic salt generation
+- **Recovery Code Hashing**: Secure one-way hashing of recovery codes
+- **No Plaintext Storage**: No sensitive data stored in plaintext
+- **Input Validation**: Comprehensive input sanitization and validation
+
+## Database Schema
+
+The authentication system uses the following key tables:
+
+- **users**: User accounts with role-based access control
+- **roles**: Hierarchical role definitions
+- **passkeys**: WebAuthn credential storage
+- **recovery_codes**: One-time recovery codes
+- **admin_invitations**: Secure admin invitation system
+- **sessions**: Secure session management
+
+## Development and Testing
+
+### Running Locally
+
+1. **Setup Database**: Ensure PostgreSQL is running with migrations applied
+2. **Bootstrap Admin**: Run the bootstrap command to create first admin
+3. **Start Server**: Run the API server with appropriate environment
+4. **Test Authentication**: Use the Flutter app or API tests
+
+### Testing WebAuthn
+
+WebAuthn requires HTTPS in production browsers. For local testing:
+
+```bash
+# Use mkcert for local HTTPS
+mkcert -install
+mkcert localhost 127.0.0.1 ::1
+
+# Set environment for local development
+export WEBAUTHN_RP_ID=localhost
+export WEBAUTHN_RP_ORIGIN=https://localhost:8080
+```
+
+## User Experience
+
+### Signup Flow
+
+1. **Username Selection**: User chooses a unique username
+2. **Real-time Validation**: Immediate feedback on username availability
+3. **Passkey Creation**: Browser prompts for passkey registration
+4. **Account Creation**: Automatic account creation with passkey
+
+### Login Flow
+
+1. **Passkey Detection**: System shows available passkeys
+2. **Biometric Prompt**: Browser authenticates with passkey
+3. **Session Creation**: Secure session established
+4. **Redirect**: User directed to dashboard
+
+### Security Settings
+
+Users can manage their security through the Settings > Security page:
+
+- **Device Management**: View, add, remove, and label passkeys
+- **Recovery Codes**: Generate new recovery codes
+- **Password Options**: Add or remove password fallback
+- **Account Recovery**: Secure account recovery options
+
+## Troubleshooting
+
+### Common Issues
+
+1. **WebAuthn Not Supported**: Use a modern browser (Chrome, Firefox, Safari, Edge)
+2. **HTTPS Required**: WebAuthn requires HTTPS in production environments
+3. **Device Compatibility**: Ensure devices support FIDO2/WebAuthn
+4. **Database Connection**: Verify database connection and migrations
+
+### Bootstrap Issues
+
+1. **Permission Denied**: Ensure proper file permissions on bootstrap binary
+2. **Database Connection**: Check DATABASE_URL configuration
+3. **Port Conflicts**: Ensure database port is accessible
+
+### Recovery Process
+
+If a user loses access to all passkeys:
+
+1. **Use Recovery Code**: Enter one of the 10 recovery codes
+2. **Contact Admin**: Admins can assist with account recovery
+3. **Re-register Passkey**: Set up new passkeys after recovery
+4. **Generate New Recovery Codes**: Replace used recovery codes
+
+## Monitoring and Maintenance
+
+### Key Metrics
+
+Monitor these metrics for system health:
+
+- Authentication success/failure rates
+- Passkey registration and usage patterns
+- Recovery code usage frequency
+- Admin action audit logs
+- Session expiration and renewal rates
+
+### Maintenance Tasks
+
+Regular maintenance includes:
+
+- Clean up expired sessions and recovery codes
+- Review audit logs for suspicious activity
+- Update role assignments as needed
+- Monitor WebAuthn compatibility with browser updates
+
+## Support and Documentation
+
+For additional support:
+
+- **Technical Issues**: Check application logs and database status
+- **Security Concerns**: Review audit logs and user activity
+- **Feature Requests**: Follow the contribution guidelines
+- **Documentation Updates**: Keep this document current with system changes
+
+---
+
+**Last Updated**: January 2026
+**Version**: 1.0
+**Compatibility**: WebAuthn Level 2, FIDO2
\ No newline at end of file
diff --git a/go_cloud_bak/go_cloud_backup.tar.gz b/go_cloud_bak/go_cloud_backup.tar.gz
deleted file mode 100644
index bcc7840..0000000
Binary files a/go_cloud_bak/go_cloud_backup.tar.gz and /dev/null differ
diff --git a/scripts/auto-deploy.sh b/scripts/auto-deploy.sh
new file mode 100755
index 0000000..ff026c0
--- /dev/null
+++ b/scripts/auto-deploy.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+# Daily auto-deploy script for Flutter/Go projects
+# Runs at 3AM daily - no more disruptive deployments!
+# Run as root/admin - no extra users needed!
+
+set -e
+
+# Configuration
+GIT_REPO="https://lab.b0esche.cloud/b0esche/b0esche_cloud.git"
+DEPLOY_DIR="/opt/auto-deploy/b0esche_cloud_rollout"
+BUILD_DIR="/opt/go/data/postgres/backend/go_cloud"
+LOG_FILE="/var/log/auto-deploy.log"
+TIMEOUT=1800 # 30 minutes for Flutter build (increased from default)
+SKIP_IF_RECENT_HOURS=2 # Skip if deployed within last 2 hours
+
+# Logging
+exec > >(tee -a "$LOG_FILE") 2>&1
+
+# Check if we should skip deployment
+LAST_DEPLOY_FILE="/tmp/last_deploy_time"
+if [ -f "$LAST_DEPLOY_FILE" ]; then
+ LAST_DEPLOY=$(cat "$LAST_DEPLOY_FILE")
+ CURRENT_TIME=$(date +%s)
+ if [ $((CURRENT_TIME - LAST_DEPLOY)) -lt $((SKIP_IF_RECENT_HOURS * 3600)) ]; then
+ echo "=== Skipping deployment - recent deploy was less than $SKIP_IF_RECENT_HOURS hours ago ==="
+ echo "=== Auto-deploy skipped at $(date) ==="
+ exit 0
+ fi
+fi
+
+echo "=== Scheduled auto-deploy started at $(date) ==="
+
+# Create deploy directory if it doesn't exist
+mkdir -p "$DEPLOY_DIR"
+cd "$DEPLOY_DIR"
+
+echo "Pulling latest changes..."
+if [ -d ".git" ]; then
+ git fetch origin
+ git reset --hard origin/main
+else
+ git clone "$GIT_REPO" .
+fi
+
+echo "=== Deploying Backend ==="
+# Copy backend code to build directory
+echo "Copying backend code to build directory..."
+mkdir -p "$BUILD_DIR"
+cp -r go_cloud/* "$BUILD_DIR/"
+
+# Build and start backend from traefik directory
+cd /opt/traefik
+echo "Building go-backend container..."
+docker-compose build --no-cache go-backend
+echo "Recreating go-backend container with fresh environment..."
+docker-compose up -d --force-recreate go-backend
+
+echo "Backend deployed successfully!"
+
+echo "=== Deploying Frontend ==="
+# Build Flutter for web with proper timeout
+echo "Building Flutter web app..."
+FRONTEND_DIR="$DEPLOY_DIR/b0esche_cloud"
+cd "$FRONTEND_DIR"
+timeout 900 sudo -u admin /opt/flutter/bin/flutter build web --release || {
+ echo "Flutter build failed or timed out"
+ exit 1
+}
+
+# Copy built files to nginx volume
+echo "Copying built files to web server..."
+rm -rf /opt/traefik/web/*
+cp -r build/web/* /opt/traefik/web/
+
+# Restart nginx container
+echo "Restarting flutter-web container..."
+cd /opt/traefik
+docker-compose up -d --force-recreate flutter-web
+
+echo "=== Deployment completed successfully at $(date) ==="
+
+# Record deployment time
+date +%s > "$LAST_DEPLOY_FILE"
+
+# Health checks
+echo "=== Running health checks ==="
+sleep 10
+
+if curl -f -s https://go.b0esche.cloud/health > /dev/null 2>&1; then
+ echo "β
Backend health check passed"
+else
+ echo "β Backend health check failed"
+fi
+
+if curl -f -s https://www.b0esche.cloud > /dev/null 2>&1; then
+ echo "β
Frontend health check passed"
+else
+ echo "β Frontend health check failed"
+fi
+
+echo "=== Scheduled auto-deploy completed ==="
diff --git a/scripts/backup.sh b/scripts/backup.sh
new file mode 100755
index 0000000..b296df2
--- /dev/null
+++ b/scripts/backup.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+# b0esche.cloud Backup Script
+# Usage: ./backup.sh
+
+set -e
+
+DATE=$(date +%Y%m%d_%H%M%S)
+BACKUP_DIR="/opt/backups/b0esche_cloud/$DATE"
+RETENTION_DAYS=30
+
+echo "Starting backup for b0esche.cloud - $DATE"
+
+# Create backup directory
+mkdir -p "$BACKUP_DIR"
+
+echo "Backing up Go backend PostgreSQL database..."
+docker exec go-postgres pg_dump -U go_backend -Fc go_backend > "$BACKUP_DIR/go_backend.sqlc"
+
+echo "Backing up Nextcloud database..."
+docker exec nextcloud-db mysqldump -u nextcloud -pSu11Fd02!!! nextcloud > "$BACKUP_DIR/nextcloud.sql"
+
+echo "Backing up Traefik certificates..."
+cp -r /opt/traefik/acme "$BACKUP_DIR/"
+
+echo "Backing up configuration files..."
+cp /opt/go/.env.production "$BACKUP_DIR/"
+cp /opt/go/docker-compose.yml "$BACKUP_DIR/go-docker-compose.yml"
+cp /opt/flutter/docker-compose.yml "$BACKUP_DIR/flutter-docker-compose.yml"
+cp /opt/flutter/nginx.conf "$BACKUP_DIR/"
+cp /opt/traefik/docker-compose.yml "$BACKUP_DIR/traefik-docker-compose.yml"
+cp /opt/traefik/traefik.yml "$BACKUP_DIR/"
+
+echo "Backing up Docker volumes..."
+docker run --rm -v nextcloud_data_31:/data -v "$BACKUP_DIR":/backup alpine tar czf /backup/nextcloud_data.tar.gz -C /data .
+
+echo "Compressing backup..."
+cd /opt/backups/b0esche_cloud
+tar czf "$DATE.tar.gz" "$DATE"
+rm -rf "$DATE"
+
+echo "Backup completed: /opt/backups/b0esche_cloud/$DATE.tar.gz"
+
+# Clean up old backups
+echo "Cleaning up backups older than $RETENTION_DAYS days..."
+find /opt/backups/b0esche_cloud -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
+
+echo "Backup process completed successfully!"
+
+# Show backup size
+ls -lh "/opt/backups/b0esche_cloud/$DATE.tar.gz"
\ No newline at end of file
diff --git a/scripts/deploy-now.sh b/scripts/deploy-now.sh
new file mode 100755
index 0000000..e17f806
--- /dev/null
+++ b/scripts/deploy-now.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+# Manual deploy script - call this when you want immediate deployment
+# Usage: ./deploy-now.sh
+
+echo "π Starting immediate deployment..."
+
+/opt/scripts/auto-deploy.sh
+
+echo "β
Manual deployment completed!"
\ No newline at end of file
diff --git a/scripts/monitor.sh b/scripts/monitor.sh
new file mode 100755
index 0000000..37a8b9b
--- /dev/null
+++ b/scripts/monitor.sh
@@ -0,0 +1,120 @@
+#!/bin/bash
+# b0esche.cloud Monitoring Script
+# Usage: ./monitor.sh
+
+set -e
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+echo "=== b0esche.cloud Service Status ==="
+echo
+
+# Check critical services
+services=("traefik" "go-backend" "go-postgres" "flutter-web" "nextcloud" "nextcloud-db" "collabora")
+
+for service in "${services[@]}"; do
+ if docker ps --format "table {{.Names}}" | grep -q "^$service$"; then
+ echo -e "${GREEN}β${NC} $service is running"
+ else
+ echo -e "${RED}β${NC} $service is not running"
+ fi
+done
+
+echo
+echo "=== Service Health Checks ==="
+echo
+
+# HTTP/HTTPS health checks
+echo -n "Flutter Web (www.b0esche.cloud): "
+if curl -s --max-time 5 https://www.b0esche.cloud | grep -q "b0esche_cloud"; then
+ echo -e "${GREEN}OK${NC}"
+else
+ echo -e "${RED}FAILED${NC}"
+fi
+
+echo -n "Go Backend (go.b0esche.cloud): "
+if curl -s --max-time 5 https://go.b0esche.cloud/health | grep -q "ok"; then
+ echo -e "${GREEN}OK${NC}"
+else
+ echo -e "${RED}FAILED${NC}"
+fi
+
+echo -n "Nextcloud (storage.b0esche.cloud): "
+if curl -s --max-time 5 -I https://storage.b0esche.cloud | grep -q "HTTP/2 200"; then
+ echo -e "${GREEN}OK${NC}"
+else
+ echo -e "${RED}FAILED${NC}"
+fi
+
+echo -n "Collabora (of.b0esche.cloud): "
+if curl -s --max-time 5 -I https://of.b0esche.cloud | grep -q "HTTP/2"; then
+ echo -e "${GREEN}OK${NC}"
+else
+ echo -e "${YELLOW}DEGRADED${NC}"
+fi
+
+echo
+echo "=== Resource Usage ==="
+echo
+
+# Show container resource usage
+docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}" | grep -E "(traefik|go-backend|flutter-web|nextcloud|collabora)"
+
+echo
+echo "=== Recent Error Logs ==="
+echo
+
+# Show recent error logs from each service
+for service in traefik go-backend nextcloud collabora; do
+ errors=$(docker logs "$service" --since=1h 2>&1 | grep -i error | tail -3 | wc -l)
+ if [ "$errors" -gt 0 ]; then
+ echo -e "${YELLOW}$service:${NC} $errors errors in last hour"
+ docker logs "$service" --since=1h 2>&1 | grep -i error | tail -3 | sed 's/^/ /'
+ fi
+done
+
+echo
+echo "=== SSL Certificate Status ==="
+echo
+
+# Check certificate expiry for main domains
+domains=("www.b0esche.cloud" "go.b0esche.cloud" "storage.b0esche.cloud" "of.b0esche.cloud")
+
+for domain in "${domains[@]}"; do
+ expiry=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null | openssl x509 -noout -dates 2>/dev/null | grep notAfter | cut -d= -f2)
+ if [ -n "$expiry" ]; then
+ expiry_epoch=$(date -d "$expiry" +%s)
+ current_epoch=$(date +%s)
+ days_left=$(( (expiry_epoch - current_epoch) / 86400 ))
+
+ if [ "$days_left" -lt 7 ]; then
+ echo -e "${RED}$domain: ${NC}Expires in $days_left days"
+ elif [ "$days_left" -lt 30 ]; then
+ echo -e "${YELLOW}$domain: ${NC}Expires in $days_left days"
+ else
+ echo -e "${GREEN}$domain: ${NC}Expires in $days_left days"
+ fi
+ else
+ echo -e "${RED}$domain: ${NC}Certificate check failed"
+ fi
+done
+
+echo
+echo "=== Disk Usage ==="
+echo
+
+# Show disk usage for critical directories
+echo "PostgreSQL data:"
+du -sh /opt/go/data/postgres 2>/dev/null || echo " Not accessible"
+
+echo "Backup directory:"
+du -sh /opt/backups 2>/dev/null || echo " Not found"
+
+echo "Docker volumes:"
+docker system df --format "table {{.Type}}\t{{.TotalCount}}\t{{.Size}}"
+
+echo
+echo "=== Monitoring Complete ==="
\ No newline at end of file
diff --git a/scripts/webhook-server.py b/scripts/webhook-server.py
new file mode 100755
index 0000000..6cd2ec9
--- /dev/null
+++ b/scripts/webhook-server.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python3
+# Simple webhook server for Gitea
+# Listens for push events and triggers auto-deploy
+
+import http.server
+import socketserver
+import json
+import subprocess
+import os
+import hmac
+import hashlib
+from urllib.parse import urlparse
+
+# Configuration
+PORT = 8080
+SECRET = 'your-webhook-secret' # Change this!
+DEPLOY_SCRIPT = '/opt/scripts/auto-deploy.sh'
+
+class WebhookHandler(http.server.BaseHTTPRequestHandler):
+ def do_POST(self):
+ if self.path == '/webhook':
+ try:
+ # Read the payload
+ content_length = int(self.headers['Content-Length'])
+ post_data = self.rfile.read(content_length)
+
+ # Verify signature (optional but recommended)
+ signature = self.headers.get('X-Gitea-Signature', '')
+ if signature:
+ expected_sig = hmac.new(
+ SECRET.encode(),
+ post_data,
+ hashlib.sha256
+ ).hexdigest()
+ expected_sig = f'sha256={expected_sig}'
+
+ if not hmac.compare_digest(signature, expected_sig):
+ self.send_response(401)
+ self.end_headers()
+ self.wfile.write(b'Invalid signature')
+ return
+
+ # Parse the webhook payload
+ data = json.loads(post_data.decode('utf-8'))
+
+ # Only deploy on manual trigger (with "deploy" in commit message)
+ commit_message = data.get('commits', [{}])[0].get('message', '').lower()
+
+ if 'deploy now' in commit_message or 'manual deploy' in commit_message:
+ print(f"Manual deploy requested: {commit_message}")
+
+ # Run the deploy script in background
+ subprocess.Popen([
+ 'nohup', 'bash', '/opt/scripts/deploy-now.sh'
+ ], stdout=open('/var/log/webhook-deploy.log', 'a'),
+ stderr=subprocess.STDOUT)
+
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'Manual deployment triggered')
+ else:
+ print(f"Ignoring push - not a manual deploy trigger")
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'Push received - daily deploy scheduled for 3AM')
+
+ except Exception as e:
+ print(f"Webhook error: {e}")
+ self.send_response(500)
+ self.end_headers()
+ self.wfile.write(b'Internal server error')
+ else:
+ self.send_response(404)
+ self.end_headers()
+ self.wfile.write(b'Not found')
+
+ def do_GET(self):
+ if self.path == '/health':
+ self.send_response(200)
+ self.end_headers()
+ self.wfile.write(b'OK')
+ else:
+ self.send_response(404)
+ self.end_headers()
+ self.wfile.write(b'Not found')
+
+if __name__ == '__main__':
+ os.makedirs('/var/log', exist_ok=True)
+
+ with socketserver.TCPServer(("", PORT), WebhookHandler) as httpd:
+ print(f"Webhook server listening on port {PORT}")
+ httpd.serve_forever()
\ No newline at end of file