- Python 79.7%
- HTML 12%
- CSS 4.5%
- JavaScript 3.5%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Test and Build FreeCAD PLM Images / build-image (push) Successful in 6m36s
|
||
| .forgejo/workflows | ||
| docker | ||
| freecad_plm | ||
| planning | ||
| plm | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| CHANGELOG.md | ||
| docker-compose.image.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| manage.py | ||
| README.md | ||
| requirements.txt | ||
| VERSION | ||
FreeCAD-PLM
Ein neues Django-basiertes PLM/PDM fuer FreeCAD-Dateien.
Lokal starten
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python manage.py migrate
.venv/bin/python manage.py setup_plm_roles
.venv/bin/python manage.py createsuperuser
.venv/bin/python manage.py runserver
Die PLM-Oberflaeche startet unter http://127.0.0.1:8000/ und nutzt http://127.0.0.1:8000/login/ fuer die normale Anmeldung. Die technische Django-Admin-Oberflaeche liegt weiterhin unter http://127.0.0.1:8000/admin/.
Serverbetrieb Mit Docker Compose
Der empfohlene Serverpfad nutzt Docker Compose mit PostgreSQL, lokalen Datenverzeichnissen und einem separaten Worker. Web und Worker werden aus getrennten Docker-Targets gebaut. Beide enthalten die PLM-Anwendung; nur das Worker-Image enthält FreeCAD/FreeCADCmd.
Der Forgejo-Workflow in .forgejo/workflows/build-image.yml baut bei jedem Push nach main oder master automatisch zwei Images aus dem lokalen Dockerfile, fuehrt die Django-Tests aus und veroeffentlicht nur bei bestandenen Tests. Das Web-Image nutzt das Build-Target web ohne FreeCAD und bleibt dadurch klein; nur das Target worker enthaelt das auf FreeCAD 1.1.1 gepinnte und per SHA-256 gepruefte offizielle AppImage:
git.home.schumbi.de/ralf/freecad-plm-web:latest
git.home.schumbi.de/ralf/freecad-plm-web:<commit-sha>
git.home.schumbi.de/ralf/freecad-plm-worker:latest
git.home.schumbi.de/ralf/freecad-plm-worker:<commit-sha>
Server Mit Fertigem Image Starten
git clone ssh://home.schumbi.de/ralf/freecad-plm.git /opt/freecad-plm
cd /opt/freecad-plm
cp .env.example .env
$EDITOR .env
In .env mindestens setzen:
DJANGO_SECRET_KEY=replace-with-a-long-random-secret
DJANGO_ALLOWED_HOSTS=plm.example.local,localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=https://plm.example.local
PLM_PUBLIC_URL=https://plm.example.local
DJANGO_SECURE_SSL_REDIRECT=0
DJANGO_SECURE_HSTS_SECONDS=0
DJANGO_SESSION_COOKIE_SECURE=1
DJANGO_CSRF_COOKIE_SECURE=1
PLM_LOG_LEVEL=INFO
DJANGO_LOG_LEVEL=INFO
DJANGO_DB_LOG_LEVEL=WARNING
GUNICORN_LOG_LEVEL=info
GUNICORN_ACCESS_LOG=1
POSTGRES_PASSWORD=replace-with-a-strong-database-password
PLM_WEB_IMAGE=git.home.schumbi.de/ralf/freecad-plm-web:latest
PLM_WORKER_IMAGE=git.home.schumbi.de/ralf/freecad-plm-worker:latest
PLM_USER=plm
PLM_UID=1000
PLM_GID=1000
FREECADCMD_COMMAND=freecadcmd
PLM_MAX_FCSTD_UPLOAD_BYTES=200000000
PLM_MAX_CAD_UPLOAD_BYTES=200000000
PLM_MAX_PROJECT_ZIP_BYTES=500000000
PLM_MAX_ZIP_MEMBERS=2000
PLM_MAX_ZIP_UNCOMPRESSED_BYTES=2147483648
PLM_MAX_ZIP_MEMBER_BYTES=200000000
BAMBUDDY_URL=http://bambuddy.example.local:8000
BAMBUDDY_API_KEY=bb_...
BAMBUDDY_TIMEOUT_SECONDS=10
BAMBUDDY_SOURCE_SYNC_ENABLED=0
BAMBUDDY_SOURCE_SYNC_PRINTER_IDS=
Das Runtime-Image enthaelt den User plm mit UID/GID 1000:1000. PLM_USER sollte deshalb auf plm bleiben. PLM_UID und PLM_GID dokumentieren, wem die lokalen Verzeichnisse auf dem Host gehoeren sollen; die Werte zeigt id oder id <user>.
Die PLM_MAX_*-Werte begrenzen FCStd-, STEP-/STL-, Projekt-ZIP- und 3MF-Uploads gegen sehr große Dateien und ZIP-Bomben. Die Defaults sind für ein LAN-Team konservativ und können bei Bedarf höher gesetzt werden.
Für lesende Bambuddy-Abfragen genügt ein eigener API-Key mit Read Status.
Der automatische Source-3MF- und Revisionslink-Sync benötigt zusätzlich
Manage Archives sowie
eine explizite Drucker-ID, beispielsweise
BAMBUDDY_SOURCE_SYNC_PRINTER_IDS=1. Der Key bleibt in der Laufzeitumgebung
und wird weder in der Datenbank noch im Browser ausgegeben.
PLM_PUBLIC_URL ist die von Bambuddy aus erreichbare Browser-Basisadresse des
PLM. Der Worker setzt daraus bei laufenden und abgeschlossenen Drucken einen
Link direkt auf die eindeutig erkannte Revision; bereits vorhandene externe
Links werden nicht überschrieben.
BAMBUDDY_TIMEOUT_SECONDS darf zwischen 1 und 60 Sekunden liegen. Unter
Verwaltung -> Integrationen zeigt der Verbindungstest auch, ob der Key den
Source-Upload ausführen darf.
Der Compose-Worker laeuft zusaetzlich mit cap_drop: ALL, no-new-privileges, read-only Root-FS, tmpfs fuer /tmp und /var/tmp sowie einfachen CPU-/RAM-/PID-Grenzen.
Lokale Verzeichnisse fuer Modelle/Uploads und statische Dateien anlegen:
mkdir -p storage staticfiles
sudo chown -R 1000:1000 storage staticfiles
Start:
docker compose -f docker-compose.image.yml pull
docker compose -f docker-compose.image.yml up -d
storage/ liegt neben der Compose-Datei und enthaelt hochgeladene Modelle, Revisionen und erzeugte Artefakte. staticfiles/ enthaelt nur neu generierbare Django-Static-Dateien.
Die verbindliche Reihenfolge fuer Update, Zustandspruefung, konsistentes Backup
und Restore-Test steht in
planning/PRODUCTION_CHECKLIST.md.
Nach dem ersten Start:
docker compose -f docker-compose.image.yml exec web python manage.py setup_plm_roles
docker compose -f docker-compose.image.yml exec web python manage.py createsuperuser
Betrieb Hinter Nginx
Wenn Django hinter einem Reverse Proxy per HTTPS erreichbar ist, muessen die
oeffentlichen Hosts und Origins in .env stehen:
DJANGO_ALLOWED_HOSTS=jellyfin.schumbi.de,localhost,127.0.0.1
DJANGO_CSRF_TRUSTED_ORIGINS=https://jellyfin.schumbi.de
PLM_HTTP_PORT=8000
Eine einfache nginx-Site fuer den lokalen Compose-Port:
server {
listen 443 ssl http2;
server_name jellyfin.schumbi.de;
ssl_certificate /etc/letsencrypt/live/jellyfin.schumbi.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jellyfin.schumbi.de/privkey.pem;
client_max_body_size 512m;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
}
}
Nach Aenderungen an .env den Web-Container neu erstellen:
docker compose -f docker-compose.image.yml up -d --force-recreate web worker
Debugging Und Logs
Web- und Worker-Logs landen auf stdout/stderr und sind direkt ueber Docker Compose abrufbar:
cd /opt/freecad-plm
docker compose -f docker-compose.image.yml logs -f --tail=200 web
docker compose -f docker-compose.image.yml logs -f --tail=200 worker
docker compose -f docker-compose.image.yml logs -f --tail=300 web worker
Fuer die lokale Testing-Instanz entsprechend:
cd ~/freecad-plm-testing
docker compose -f docker-compose.image.yml logs -f --tail=300 web worker
Die Ausfuehrlichkeit laesst sich in .env steuern:
PLM_LOG_LEVEL=DEBUG
DJANGO_LOG_LEVEL=DEBUG
DJANGO_DB_LOG_LEVEL=WARNING
GUNICORN_LOG_LEVEL=debug
GUNICORN_ACCESS_LOG=1
PLM_LOG_LEVEL: App-Logger fuerplm.*und Root-Logger.DJANGO_LOG_LEVEL: Django-Logger inklusive Request-/Exception-Logging.DJANGO_DB_LOG_LEVEL: SQL-Logging ueberdjango.db.backends;DEBUGist sehr laut und nur fuer gezielte Datenbankdiagnose gedacht.GUNICORN_LOG_LEVEL: Gunicorn-Loglevel.GUNICORN_ACCESS_LOG:1schreibt HTTP-Access-Logs nach stdout,0deaktiviert sie.
Nach Aenderungen an diesen Werten:
docker compose -f docker-compose.image.yml up -d --force-recreate web worker
DJANGO_DEBUG=1 kann in einer lokalen Testumgebung zusaetzlich helfen, sollte
aber nicht fuer oeffentlich erreichbare Instanzen gesetzt werden.
Image Manuell Bauen
Normalerweise baut der Forgejo-Workflow in diesem Repo die Images. Manuell geht es so (Web ohne FreeCAD, Worker mit FreeCAD):
git clone ssh://home.schumbi.de/ralf/freecad-plm.git /opt/freecad-plm-build
cd /opt/freecad-plm-build
docker build --target web -t git.home.schumbi.de/ralf/freecad-plm-web:latest .
docker build --target worker -t git.home.schumbi.de/ralf/freecad-plm-worker:latest .
docker push git.home.schumbi.de/ralf/freecad-plm-web:latest
docker push git.home.schumbi.de/ralf/freecad-plm-worker:latest
Image-Build Ausloesen
Im Normalfall reicht ein Push ins App-Repo:
cd /home/ralf/devel/freecad-plm/freecad-plm
git push
Der Forgejo-Workflow Test and Build FreeCAD PLM Images startet bei Push nach main oder
master automatisch. Er baut Web- und Worker-Image, fuehrt die Tests aus und pusht nur
bei gruenen Tests. Den Lauf findest du in Forgejo unter:
ralf/freecad-plm -> Actions -> Test and Build FreeCAD PLM Images
Wenn ein Build ohne neuen Commit erneut laufen soll, kann der Workflow dort auch
manuell ueber Run workflow gestartet werden. Nach einem erfolgreichen Lauf sind
die Registry-Images aktualisiert:
git.home.schumbi.de/ralf/freecad-plm-web:latest
git.home.schumbi.de/ralf/freecad-plm-web:<commit-sha>
git.home.schumbi.de/ralf/freecad-plm-worker:latest
git.home.schumbi.de/ralf/freecad-plm-worker:<commit-sha>
Updates
Wenn das Image neu gebaut wurde:
cd /opt/freecad-plm
git pull
docker compose -f docker-compose.image.yml pull
docker compose -f docker-compose.image.yml up -d
Lokaler Compose-Build
Alternativ kann das App-Repo lokal ein Image bauen. Das ist fuer Entwicklung praktisch, auf dem Server aber langsamer als das fertige Registry-Image:
docker compose up -d --build
Rollen
Die V1-Rollen werden als Django-Gruppen angelegt:
.venv/bin/python manage.py setup_plm_roles
reader: ansehen und herunterladeneditor: ansehen, herunterladen und Revisionen hochladenadmin: volle PLM-Verwaltung
PLM-Admins koennen Benutzer und Addon-Tokens in der normalen Weboberflaeche
unter Verwaltung pflegen. Die normale Anmeldung fuehrt direkt in das PLM-WebUI.
Der Django-Admin unter /admin/ bleibt als technische Fallback-Verwaltung
erhalten und ist von der Login-Seite aus verlinkt.
Die Web-Verwaltung kann:
- Benutzer anlegen, aktivieren/deaktivieren und Rollen setzen.
- Passwoerter fuer Benutzer neu setzen.
- API-Tokens fuer Benutzer anlegen, bearbeiten und widerrufen.
Token-Rechte werden ueber Presets vergeben:
Nur Lesen:readAddon Standard:read,write,checkoutAdmin/Vollzugriff:read,write,checkout,admin
Admin/Vollzugriff kann nur fuer Benutzer mit PLM-Admin-Rolle oder Superuser
vergeben werden. Der Klartext eines API-Tokens wird nur direkt nach dem
Anlegen angezeigt; danach bleibt nur der Prefix sichtbar.
Kurzworkflow
- Projekt als
admin/Superuser in der PLM-Oberflaeche anlegen oder vorhandenes Projekt oeffnen. - Teil oder Baugruppe im Projekt mit initialer
.FCStd-,.step-,.stp- oder.stl-Datei anlegen. - Bei FCStd die FreeCAD-Metadaten prüfen. Teilenummer und Name können leer bleiben; dann nutzt das PLM FreeCAD-
Id/Label. Bei STEP/STL wird der Dateiname als Name verwendet. Fehlt eine Nummer, vergibt das PLM automatischP-001,P-002, ... - Neue Revisionen werden automatisch kanonisch als
R0001,R0002, ... vergeben; alte oder testweise abweichende Codes werden bei der naechsten Nummer ignoriert. - Beim Hochladen einer neuen Revision fehlende oder abweichende FreeCAD-Property
PLMRevisionverwerfen oder als PLM-normalisierte Kopie speichern. - Optional Anmerkungen ergaenzen.
- Optional Revision freigeben (nur
admin/Superuser). - Aeltere freigegebene Revision als obsolet markieren (nur
admin/Superuser), wenn eine neuere Revision gueltig ist. - Globale Suche in der Topbar nutzen: Projekte, Teile, Revisionen und Dateipfade finden (
/search/?q=...).
Suche
Die globale Suche in der Topbar durchsucht Projekte, Teile, Revisionen und Dateipfade in Projektständen. Auf der Ergebnisseite kann zusätzlich nach Projekt, Revisionsstatus, CAD-Format und Teilekategorie gefiltert werden; die Facetten funktionieren auch ohne Suchtext. Auf Listen-Seiten gibt es weiterhin einen lokalen Filter in der jeweiligen Toolbar.
Die Teilseite verbindet Revisionen, Freigaben, synchronisierte 3MF-Slicer-Stände, Fertigungsdateien und Fertigungsläufe in einem gemeinsamen Lebenszyklus. Baugruppen zeigen außerdem einen aufklappbaren Referenzbaum aus dem historischen Projektstand. CAD-Revisionen und Fertigungsdateien können per Drag-and-drop hochgeladen werden. Im 3D-Viewer lassen sich PLM-Anmerkungen an einem Modellpunkt verankern.
Projektstaende
Projekte mit .FCStd-, .step-, .stp- und .stl-Dateien können als ZIP importiert werden. Das PLM legt einen Projektstand an und speichert, welche Revisionen unter welchen relativen Pfaden zusammengehören. Der Projektstand kann wieder als ZIP heruntergeladen werden.
STEP und STL können entweder primäre, unveränderliche CAD-Revisionen sein oder als von einer FCStd-Revision abgeleitete Artefakte vorliegen. Primäre STL-Dateien werden direkt im Web-Viewer angezeigt. Primäre STEP-Dateien laufen für Vorschau und Analyse durch den FreeCADCmd-Worker. Nur FCStd-Revisionen können ausgecheckt und bearbeitet werden; STEP/STL in einem FCStd-Projektstand bleiben schreibgeschützte Begleitdateien.
Wird später eine FCStd-Revision zu einem bisher als STEP/STL geführten Teil hochgeladen, kann im Uploadformular optional ein Projektstand ausgewählt werden. Das PLM erzeugt dann einen neuen Stand, ersetzt darin den bisherigen STEP/STL-Pfad durch den FCStd-Pfad und lässt den gewählten Ausgangsstand unverändert. Ohne Auswahl wird nur die neue Revision angelegt.
Der normale Download einer Revision liefert eine einzelne .FCStd nur dann, wenn sie keine FreeCAD-Referenzen enthaelt. Hat eine Datei Referenzen, liefert der Download automatisch ein ZIP mit der Datei und ihren rekursiv referenzierten Dateien aus demselben Projektstand.
Projektstand, Planung und V1-Abnahme-Checkliste stehen in planning/; fuer die manuelle V1-Abnahme siehe planning/V1_ACCEPTANCE.md.
FreeCAD-Addon-API
Das PLM stellt JSON-Endpunkte unter /api/ bereit. Sie sind fuer ein vanilla-FreeCAD-Addon gedacht und unterstuetzen Bearer Tokens:
.venv/bin/python manage.py create_api_token addon-user "FreeCAD Addon" --scope read --scope write --scope checkout
Der ausgegebene Token wird nur einmal angezeigt und danach als Header gesendet:
Authorization: Bearer plm_pat_...
Token-Scopes:
-
read: Projekte, Teile, Revisionen und Dateien lesen -
write: Teile bearbeiten/anlegen und Anmerkungen schreiben -
checkout: Checkout, Check-in und Cancel -
admin: Projektanlage/-bearbeitung ueber API -
GET/POST /api/projects/ -
POST /api/projects/import/ -
GET/POST /api/projects/<id>/ -
POST /api/projects/<id>/snapshots/import/ -
GET/POST /api/projects/<id>/parts/ -
POST /api/projects/<id>/parts/create-fcstd/ -
GET/POST /api/parts/<id>/ -
GET /api/revisions/<id>/ -
POST /api/revisions/<id>/notes/ -
GET /api/revisions/<id>/file/ -
GET /api/revisions/<id>/manifest/ -
GET/POST /api/revisions/<id>/slicer-project/ -
GET /api/manufacturing-files/<id>/file/ -
POST /api/revisions/<id>/checkout/ -
GET /api/checkouts/active/ -
GET /api/checkouts/<id>/manifest/ -
POST /api/checkouts/<id>/files/add/ -
POST /api/checkouts/<id>/files/remove/ -
POST /api/checkouts/<id>/checkin/ -
POST /api/checkouts/<id>/cancel/ -
GET/POST /api/parts/<id>/annotations/ -
POST/DELETE /api/annotations/<id>/
Projektbearbeitung ueber POST /api/projects/<id>/ braucht Scope admin und
akzeptiert dieselben Stammdaten wie das WebUI: code, name, status,
project_date, description und is_archived.
Lokale FreeCAD-Dateisets koennen als Projektstand importiert werden. Das Addon
sendet dafür ein ZIP mit relativen .FCStd-, .step-, .stp- und .stl-Pfaden an
POST /api/projects/<id>/snapshots/import/ mit Scope write. Fuer den
Kombiflow "Projekt anlegen und ZIP importieren" nutzt es
POST /api/projects/import/ mit Scope admin.
Für Neues Teil nutzt das Addon
POST /api/projects/<id>/parts/create-fcstd/ mit den Scopes write und
checkout. Das Addon erzeugt die leere FCStd-Datei intern; eine vorher lokal
gespeicherte Benutzerdatei ist nicht erforderlich. Der Server legt Teil und
Revision R0001 gemeinsam an. Mit checkout_id wird die neue Datei direkt in
den lokal geöffneten Projekt-Checkout aufgenommen. Ohne checkout_id entsteht
ein eigener Checkout für das neue Teil. Schlägt die serverseitige Teilanlage
oder Aufnahme in den Checkout fehl, werden Teil, Revision und Audit-Einträge
nicht als unvollständiger Datenbankstand gespeichert.
Mit GET/POST /api/revisions/<id>/slicer-project/ verwaltet das Addon genau
einen bearbeitbaren 3MF-Slicer-Arbeitsstand je CAD-Revision. Ein Update sendet
den zuletzt gelesenen Server-Hash als base_sha256; ein veralteter Stand wird
mit HTTP 409 abgelehnt und niemals still überschrieben. Normale hochgeladene
Slicer-/Fertigungsdateien bleiben davon getrennt und unveränderlich. Der
Arbeitsstand wird im WebUI als Slicer-Projekt (Arbeitsstand) angezeigt.
Checkout ist exklusiv pro Teil/Baugruppe. Das Checkout-Manifest enthaelt Root-Datei, referenzierte Revisionen, relative Pfade, Hashes und Download-URLs. Der Check-in erzeugt nur fuer modellrelevante FCStd-Aenderungen neue unveraenderliche Revisionen; reine FreeCAD-Speicherartefakte wie GuiDocument.xml, ShapeAppearance*, LastModified*, PLMRevision, lokale Checkout-Pfade in BOM-/XML-Attributen und winziges Placement-Floating-Point-Rauschen werden durch die technische Signatur ignoriert.
FreeCADCmd
Exportjobs werden mit FREECADCMD_COMMAND ausgefuehrt. Das Docker-Worker-Image enthaelt FreeCAD 1.1.1 aus dem offiziellen x86_64-AppImage; Version und SHA-256 sind im Dockerfile fest gepinnt. Ohne eigene Einstellung versucht das PLM zuerst FreeCADCmd und faellt auf lokalen Installationen auf Flatpak org.freecad.FreeCAD mit --command=FreeCADCmd und /tmp-Freigabe zurueck, wenn Flatpak vorhanden ist.
Beispiel fuer eine explizite Flatpak-Konfiguration:
FREECADCMD_COMMAND='flatpak run --filesystem=/tmp --branch=stable --arch=x86_64 --command=FreeCADCmd org.freecad.FreeCAD' .venv/bin/python manage.py process_export_jobs
PNG-Ansichten werden ohne FreeCAD-GUI erzeugt. Der Worker exportiert die Revision mit FreeCADCmd zuerst als STEP-Artefakt und als temporaeres STL-Vorschau-Mesh. Danach rendert das PLM aus dem STL-Mesh feste PNG-Ansichten. Dafuer wird kein FreeCAD-Fenster, kein Qt-Viewport und kein xvfb-run benoetigt.
Empfohlene Server-Konfiguration:
FREECADCMD_COMMAND='freecadcmd'
PREVIEW_PNG_WIDTH=400
PREVIEW_PNG_HEIGHT=300
PROCESS_EXPORT_JOBS_INLINE=0
Mit PROCESS_EXPORT_JOBS_INLINE=0 legt die Weboberflaeche Export- und PNG-Jobs nur an. Der Docker-Worker verarbeitet sie im Hintergrund. So muss der Webprozess kein FreeCAD starten.
Auf einem Server mit nativer FreeCAD-Installation reicht meistens:
FREECADCMD_COMMAND=/usr/bin/FreeCADCmd .venv/bin/python manage.py process_export_jobs