From 98417edd8bc1a84396f9f8ac92a7da1b2e357f39 Mon Sep 17 00:00:00 2001 From: Aron Date: Wed, 5 Nov 2025 14:32:21 +0100 Subject: [PATCH] add forgejo, add jupyter --- .DS_Store | Bin 10244 -> 10244 bytes .env.example | 6 +- .github/copilot-instructions.md | 7 + .gitignore | 2 + PORTAINER_QUICKREF.md | 231 ---------------------- README.md | 66 ++++++- backup.sh | 6 +- data/.DS_Store | Bin 8196 -> 8196 bytes data/Tello_Drone_Setup.ipynb | 177 +++++++++++++++++ docker-compose.yml | 77 +++++++- forgejo/data/git/.ssh/environment | 1 + forgejo/data/gitea/conf/app.ini | 63 ++++++ forgejo/data/ssh/ssh_host_ecdsa_key | 9 + forgejo/data/ssh/ssh_host_ecdsa_key.pub | 1 + forgejo/data/ssh/ssh_host_ed25519_key | 7 + forgejo/data/ssh/ssh_host_ed25519_key.pub | 1 + forgejo/data/ssh/ssh_host_rsa_key | 38 ++++ forgejo/data/ssh/ssh_host_rsa_key.pub | 1 + jupyterhub/Dockerfile | 28 +++ jupyterhub/jupyterhub_config.py | 79 ++++++++ main.py | 2 + restore.sh | 6 +- templates/landing.html | 15 +- 23 files changed, 562 insertions(+), 261 deletions(-) delete mode 100644 PORTAINER_QUICKREF.md create mode 100644 data/Tello_Drone_Setup.ipynb create mode 100644 forgejo/data/git/.ssh/environment create mode 100644 forgejo/data/gitea/conf/app.ini create mode 100644 forgejo/data/ssh/ssh_host_ecdsa_key create mode 100644 forgejo/data/ssh/ssh_host_ecdsa_key.pub create mode 100644 forgejo/data/ssh/ssh_host_ed25519_key create mode 100644 forgejo/data/ssh/ssh_host_ed25519_key.pub create mode 100644 forgejo/data/ssh/ssh_host_rsa_key create mode 100644 forgejo/data/ssh/ssh_host_rsa_key.pub create mode 100644 jupyterhub/Dockerfile create mode 100644 jupyterhub/jupyterhub_config.py diff --git a/.DS_Store b/.DS_Store index 0503454f87368e0d59c2ffd88a8da0a8ad0e69b7..7f4c47e9b5b3e08848fdd1f8a6ee6ad83da7d43a 100644 GIT binary patch delta 641 zcmZn(XbG6$&*-)>U^hRb_GBIb3AV!AcSYM{Cu<2v!I)kGGK>=@rwdG}XJ<%b$Y&^G zNM}f8$YRLPNjD5m&d)7i00Yq$AcdwPH{Zo2DJMS(D8td}mp^S=>~TkIs#1thRgl4p zY+b|T?*b0|TtIh}G88aWGL!(_R5W>lgh&qGBA^v$5)2tYWl6}+*^)oeU^~P)IMgB> zg|dT0Ig)0{6J7fYiZaj-;EG+*%)#e5`hjYV#s8u$jwKX2T?OwO-POz zsBN>mkRlV)vMrOdL}b{KW}goGX*;<`L=MK>AR^Bs%rN<)NH~*&^W-{FvB?giJZwcL z_3hThPOcG^n4AUYZmtmxXPnF}AsNp&{ooa#(JTylz{tvEC_(o5ye0#nR&Ych$s=5c zO}-!l5%!F86(%=JC^CuFPhKV=$2M_>9>^shBt$0Pli-1JH-C`OVr08~94w_ErGa3| SY|fHmV`2*J+*~9xi5mdBzO+UF delta 389 zcmZn(XbG6$&uF(XU^hRb@?;(X2{xVrrW@T}leGk-U`#Io8ODOi=>k(GcMIA~&KFwB z!YH`LbFzf63>#~`&)5HsldXj1V9YpSIc7!$fz9>8icB8)DGUq@Yz)N=B@Br`oXL=! zoA2V1l#`zX6z7mX!z|lodE60GO$wTt$uC6ZnM4dGbBcvCS&B{W5tEo)CC0_}Q7`-A zKD)_XVk%JP<}G63j2jy)7$UyuqA0$L3-;>~hayNgF&|+j` eHvKcv#(lDalm>z+vpGwOjfu(GU~`eoByIpq;c;mI diff --git a/.env.example b/.env.example index b0919f5..9f5a7cf 100644 --- a/.env.example +++ b/.env.example @@ -45,9 +45,9 @@ BOOKSTACK_APP_KEY=base64:YOUR_BOOKSTACK_KEY_HERE # ======================================== DB_HOST=bookstack-mariadb DB_PORT=3306 -DB_DATABASE=bookstack -DB_USERNAME=bookstack -DB_PASSWORD=your_secure_database_password_here +BOOKSTACK_DB_DATABASE=bookstack +BOOKSTACK_DB_USERNAME=bookstack +BOOKSTACK_DB_PASSWORD=your_secure_database_password_here # MariaDB root password MARIADB_ROOT_PASSWORD=your_secure_root_password_here diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index df0c438..dfc408c 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -71,6 +71,13 @@ BOOKSTACK_PORT=6875 # BookStack/DB configs (see docker-compose.yml for full list) ``` +Note: this repository also contains a local `.env` with example credentials (do NOT commit real secrets). Current repository `.env` contents: +```properties +MATRIX_USER=einszwovier_bot +MATRIX_PASS=einszwo4 +``` +Prefer injecting secrets via CI environment variables or a secure vault for production. Add `MATRIX_ROOM` and/or `MATRIX_HOMESERVER` when testing Matrix flows. + ### Debugging Matrix Integration Use `get_room_id.py` to discover Matrix room IDs: ```python diff --git a/.gitignore b/.gitignore index e3cb230..f5e2f12 100644 --- a/.gitignore +++ b/.gitignore @@ -103,3 +103,5 @@ dmypy.json *.db-wal *.sqlite *.sqlite3 +.github +.venv diff --git a/PORTAINER_QUICKREF.md b/PORTAINER_QUICKREF.md deleted file mode 100644 index c1d8d9c..0000000 --- a/PORTAINER_QUICKREF.md +++ /dev/null @@ -1,231 +0,0 @@ -# Portainer Quick Reference - -## 🚀 Quick Start - -### Access Portainer -``` -http://localhost:9000 -or -http://einszwovier.local:9000 -``` - -### First Login -1. Create admin account -2. Select "Local" environment -3. Done! - -## 📊 Stack Overview: studio-einszwovier - -| Service | Port | Health Check | Purpose | -|---------|------|--------------|---------| -| web | 80 | ✅ | PDF Cost Calculator | -| bookstack | 6875 | ✅ | Documentation Wiki | -| bookstack-mariadb | - | ✅ | Database | -| synapse | 8008 | ✅ | Matrix Server | -| ollama | 11434 | ✅ | Local LLM | -| open-webui | 8080 | ✅ | LLM Interface | -| watchtower | - | ✅ | Auto-Updates | -| portainer | 9000 | ✅ | Management UI | - -## 🎯 Common Tasks - -### View All Services -**Portainer**: Stacks → studio-einszwovier -**CLI**: `docker-compose ps` - -### Restart a Service -**Portainer**: Containers → [service] → Restart -**CLI**: `docker-compose restart [service]` - -### View Logs -**Portainer**: Containers → [service] → Logs -**CLI**: `docker-compose logs -f [service]` - -### Check Health Status -**Portainer**: Containers → Look for 🟢/🔴 indicator -**CLI**: `docker-compose ps` (shows (healthy) or (unhealthy)) - -### Stop Everything -**Portainer**: Stacks → studio-einszwovier → Stop -**CLI**: `docker-compose stop` - -### Start Everything -**Portainer**: Stacks → studio-einszwovier → Start -**CLI**: `docker-compose start` - -### Update a Service -**Portainer**: Containers → [service] → Recreate -**CLI**: `docker-compose pull [service] && docker-compose up -d [service]` - -## 🔍 Troubleshooting - -### Service Shows 🔴 Unhealthy -1. Click container → Logs -2. Look for errors -3. Check health check output in Inspect tab -4. Restart if needed - -### Can't Access Portainer -```bash -docker-compose restart portainer -# Wait 30 seconds -# Try again at http://localhost:9000 -``` - -### Service Won't Start -1. Check Portainer logs for the service -2. Look for dependency issues (red containers) -3. Check resource limits (Stats tab) -4. Verify environment variables in Container → Env - -## 📋 Health Check Endpoints - -Test manually if needed: - -```bash -# Web App -curl http://localhost/ - -# BookStack -curl http://localhost:6875/ - -# Matrix Synapse -curl http://localhost:8008/health - -# Ollama -curl http://localhost:11434/api/tags - -# Open WebUI -curl http://localhost:8080/ - -# Portainer -curl http://localhost:9000/api/system/status -``` - -## 🏷️ Labels in Portainer - -All services are tagged with: -- **description**: What it does -- **maintainer**: Studio EinsZwoVier -- **watchtower.enable**: Auto-update enabled - -Filter by labels in Portainer UI! - -## 🔄 Auto-Updates (Watchtower) - -- **Schedule**: Every 24 hours -- **Action**: Pulls latest images and recreates containers -- **Which services**: Only those with `watchtower.enable=true` label -- **View updates**: Containers → watchtower → Logs - -### Disable Auto-Update for a Service -Edit docker-compose.yml, remove: -```yaml -labels: - - "com.centurylinklabs.watchtower.enable=true" -``` - -## 📈 Resource Monitoring - -**Portainer**: Container → Stats -Shows: -- CPU usage (%) -- Memory usage (MB / GB) -- Network I/O -- Block I/O - -**Limits Set**: -- web: 1GB RAM, 1 CPU -- ollama: 8GB RAM, 4 CPU - -## 🌐 Network: einszwovier_network - -All services communicate on this network. - -**View**: Networks → einszwovier_network → Connected containers - -## 💾 Volumes - -| Volume | Used By | Purpose | -|--------|---------|---------| -| portainer_data | portainer | Portainer config | -| ./data/uploads | web | PDF uploads | -| ./bookstack/* | bookstack | Wiki data | -| ./matrix/data | synapse | Matrix data | -| ./ollama | ollama | LLM models | -| ./open-webui | open-webui | Chat history | - -**Backup**: See `backup.sh` script - -## ⚙️ Useful Portainer Features - -### Execute Shell Commands -1. Containers → [service] → Console -2. Select `/bin/bash` or `/bin/sh` -3. Click Connect -4. Run commands - -### View Container Config -1. Containers → [service] → Inspect -2. See full JSON configuration -3. Copy environment variables -4. Check volume mounts - -### Duplicate Container -1. Containers → [service] → Duplicate/Edit -2. Modify settings -3. Deploy as new container - -### Container Template -1. App Templates → Custom Templates -2. Create from existing container -3. Reuse configuration - -## 🎨 Status Icons - -| Icon | Meaning | Action | -|------|---------|--------| -| 🟢 | Healthy | None needed | -| 🟡 | Starting | Wait (within start_period) | -| 🔴 | Unhealthy | Check logs | -| ⚫ | Stopped | Start container | -| 🔄 | Restarting | Wait or investigate | - -## 📞 Quick Help - -### "I can't find my containers!" -- Go to **Home** -- Select **Local** environment -- Go to **Stacks** → studio-einszwovier - -### "Health checks keep failing" -- Increase `start_period` in docker-compose.yml -- Check service logs for actual errors -- Verify network connectivity - -### "Portainer shows wrong status" -- Refresh page (F5) -- Check "Last Updated" timestamp -- Restart Portainer if stale - -## 🔐 Security Notes - -- Portainer admin password is set on first login (save it!) -- Docker socket mounted = full control (use carefully) -- HTTPS available on port 9443 (configure in Portainer settings) - -## 📱 Mobile Access - -Portainer works great on mobile: -1. Open browser on phone -2. Navigate to `http://[server-ip]:9000` -3. Same features as desktop! - -## ✅ Daily Checklist - -- [ ] All services showing 🟢 healthy -- [ ] No unusual CPU/memory spikes -- [ ] Recent watchtower update logs look good -- [ ] No red error logs in critical services - -**Portainer makes this a 30-second check!** diff --git a/README.md b/README.md index 2465c2b..0c88c01 100644 --- a/README.md +++ b/README.md @@ -11,17 +11,21 @@ ## 🎯 Features ### Core Application + - **📄 PDF Cost Calculator**: Automated ink coverage analysis with color/B&W detection - **🖼️ Course Management**: Dynamic course list with image gallery and modal viewer - **📊 Cost Estimation**: Per-page breakdown with configurable rates (€/m²) - **💬 Matrix Integration**: Automatic order submission to Matrix room ### Integrated Services + - **📚 BookStack Wiki**: Documentation and knowledge base (port 6875) - **🤖 Ollama + Open WebUI**: Local LLM chatbot interface (port 8080) - **📨 Matrix Synapse**: Print order collection and payment tracking (port 8008) - **🐳 Portainer**: Container management dashboard (port 9000) -- **🔄 Watchtower**: Automatic container updates every 24 hours +- **� JupyterHub**: Multi-user Jupyter notebook server for drone programming (port 8001) +- **🦊 Forgejo**: Self-hosted Git service for code collaboration (port 3003) +- **�🔄 Watchtower**: Automatic container updates every 24 hours --- @@ -74,35 +78,55 @@ graph TB OpenWebUI[💭 Open WebUI
:8080] Portainer[🐳 Portainer
:9000] Synapse[📨 Matrix Synapse
:8008] + JupyterHub[📓 JupyterHub
:8001
Drone Programming] + Forgejo[🦊 Forgejo Git
:3003
Code Collaboration] LP -.-> BookStack LP -.-> OpenWebUI LP -.-> Portainer + LP -.-> JupyterHub + LP -.-> Forgejo OpenWebUI --> Ollama MatrixRoom --> Synapse end + subgraph "Educational Stack" + Notebooks[📒 Jupyter Notebooks
Python Drone Code] + GitRepos[📦 Git Repositories
Project Source Code] + DronePackages[🚁 djitellopy
Tello SDK] + + JupyterHub --> Notebooks + Forgejo --> GitRepos + Notebooks -.-> DronePackages + end + subgraph "Data Persistence" Uploads[📁 data/uploads/
PDF Files] Courses[📋 data/courses.csv
Course List] MatrixDB[(🗄️ Matrix DB
homeserver.db)] BookDB[(🗄️ BookStack DB
MariaDB)] + JupyterVolumes[(💾 Jupyter Volumes
User Workspaces)] + ForgejoData[(📚 Forgejo Data
Git Repos)] Upload --> Uploads CSV --> Courses Synapse --> MatrixDB BookStack --> BookDB + JupyterHub --> JupyterVolumes + Forgejo --> ForgejoData end classDef webapp fill:#e3f2fd,stroke:#1976d2,stroke-width:2px classDef service fill:#fff3e0,stroke:#f57c00,stroke-width:2px classDef data fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px classDef matrix fill:#e8f5e9,stroke:#388e3c,stroke-width:2px + classDef edu fill:#fce4ec,stroke:#c2185b,stroke-width:2px class LP,About,Cost,Upload,Analysis,Quote webapp - class BookStack,Ollama,OpenWebUI,Portainer,Synapse service - class Uploads,Courses,MatrixDB,BookDB data + class BookStack,Ollama,OpenWebUI,Portainer,Synapse,JupyterHub,Forgejo service + class Uploads,Courses,MatrixDB,BookDB,JupyterVolumes,ForgejoData data class MatrixRoom,PDF_Upload,Summary,CSV,Images,Modal matrix + class Notebooks,GitRepos,DronePackages edu ``` --- @@ -113,47 +137,55 @@ graph TB - **Docker** & **Docker Compose** installed - **Poppler** (for pdf2image - included in Docker) -- **Port availability**: 80, 8008, 8080, 6875, 9000, 11434 +- **Port availability**: 80, 3003, 6875, 8001, 8008, 8080, 9000, 11434 ### Installation 1. **Clone the repository:** + ```bash git clone https://github.com/arontaupe/124-webapp.git cd 124-webapp ``` 2. **Configure environment:** + ```bash cp .env.example .env nano .env # Update SERVER_HOSTNAME and passwords ``` 3. **Start the stack:** + ```bash docker compose up -d --build ``` 4. **Access services:** - - Web App: http://localhost (or http://your-server) - - BookStack: http://localhost:6875 - - Open WebUI: http://localhost:8080 - - Portainer: http://localhost:9000 - - Matrix: http://localhost:8008 + - Web App: (or ) + - BookStack: + - Open WebUI: + - Portainer: + - Matrix: + - JupyterHub: + - Forgejo: ### First-Time Setup 1. **Get Matrix Room ID:** + ```bash python get_room_id.py ``` 2. **Update .env with room ID:** + ```bash MATRIX_ROOM="!YourRoomID:${SERVER_HOSTNAME}" ``` 3. **Restart web container:** + ```bash docker compose restart web ``` @@ -167,12 +199,14 @@ Courses are managed via CSV file with optional images: ### Add a Course 1. **Edit `data/courses.csv`:** + ```csv title,description,dates,offen_fuer,image My Course,Learn cool stuff,"Oct '25",Grade 10,/static/images/courses/my-course.jpg ``` 2. **Add course image (optional):** + ```bash cp my-image.jpg static/images/courses/my-course.jpg ``` @@ -180,6 +214,7 @@ Courses are managed via CSV file with optional images: 3. **Changes apply immediately** (no restart needed) ### Course Image Features + - **Thumbnail view**: 80x80px next to course info - **Hover zoom**: Expands to 200x200px on hover - **Click to enlarge**: Opens full-size modal viewer @@ -215,6 +250,11 @@ OLLAMA_PORT=11434 OPENWEBUI_PORT=8080 BOOKSTACK_PORT=6875 PORTAINER_PORT=9000 +JUPYTER_PORT=8001 +FORGEJO_PORT=3003 + +# JupyterHub Authentication +JUPYTER_PASSWORD=einszwo4 ``` See [.env.example](.env.example) for full configuration. @@ -231,12 +271,15 @@ See [.env.example](.env.example) for full configuration. | **open-webui** | ghcr.io/open-webui/open-webui | 8080 | LLM chat UI | 2 CPU, 2GB RAM | | **bookstack** | lscr.io/linuxserver/bookstack | 6875 | Documentation wiki | Default | | **bookstack-mariadb** | lscr.io/linuxserver/mariadb | 3306 | Database for BookStack | Default | +| **jupyterhub** | Custom (Python 3.13) | 8001 | Multi-user Jupyter notebooks | 2 CPU, 2GB RAM | +| **forgejo** | codeberg.org/forgejo/forgejo:11 | 3003, 222 | Git service (web, SSH) | Default | | **portainer** | portainer/portainer-ce | 9000, 9443 | Container management | Default | | **watchtower** | containrrr/watchtower | - | Auto-updates (24h) | Default | ### Health Checks All services have health checks configured: + - **web**: `curl http://localhost:8000/` - **synapse**: `curl http://localhost:8008/_matrix/static/` - **ollama**: `curl http://localhost:11434/` @@ -283,6 +326,7 @@ See [SECURITY.md](SECURITY.md) for comprehensive security guidelines. ``` Creates timestamped backups of: + - BookStack database & files - Matrix homeserver data - PDF uploads @@ -302,11 +346,13 @@ Creates timestamped backups of: This application is designed to be **fully portable**. To move to a new server: 1. **On old server:** + ```bash ./backup.sh ``` 2. **On new server:** + ```bash git clone cd 124-webapp @@ -393,7 +439,7 @@ This project is part of Studio EinsZwoVier educational initiative. Gabriele-von-Bülow-Gymnasium Tile-Brügge-Weg 63, 13509 Berlin (Tegel) -- **Email**: einszwovier@gvb-gymnasium.de +- **Email**: - **Team**: Aron Petau & Friedrich Weber - **Hours**: Tuesday - Thursday, 11:00 - 16:00 - **Location**: Room 124 diff --git a/backup.sh b/backup.sh index 1aa0355..e2404b8 100755 --- a/backup.sh +++ b/backup.sh @@ -19,9 +19,9 @@ echo "Working directory: $SCRIPT_DIR" # 1. Backup BookStack database echo "Backing up BookStack database..." docker exec bookstack-mariadb mariadb-dump \ - -u"${DB_USERNAME:-bookstack}" \ - -p"${DB_PASSWORD}" \ - "${DB_DATABASE:-bookstack}" \ + -u"${BOOKSTACK_DB_USERNAME:-bookstack}" \ + -p"${BOOKSTACK_DB_PASSWORD}" \ + "${BOOKSTACK_DB_DATABASE:-bookstack}" \ | gzip > "$BACKUP_DIR/bookstack_db_$DATE.sql.gz" # 2. Backup BookStack uploads and config diff --git a/data/.DS_Store b/data/.DS_Store index 645b94241a046573a81a67cedb0341ad6f5f7ae4..53ad94d5f9ce16612e32aff009875dff5f13cf03 100644 GIT binary patch delta 243 zcmZp1XmOa}&&aVcU^hP_$7CLXm;C95!O8i#1q@KI`H_G>TTE`gi%U{YeiBfSTeste unsere schulischen Large Language Models direkt über die Weboberfläche. + +
JupyterHub
+
Interaktive Python-Notebooks für Datenanalyse, Visualisierung und kollaboratives + Programmieren. Schreib uns eine E-Mail für Login-Daten.
+
+ + +
Forgejo Git Server
+
Versionskontrolle und Code-Hosting für kollaborative Softwareprojekte. Ideal für gemeinsame + Entwicklung und Projektmanagement.
+
+
Kontakt
Schreibe uns direkt an: einszwovier@gvb-gymnasium.de
@@ -70,7 +82,8 @@