ForgeCMS
Flask Blog & CMS mit MariaDB – Auth, Draft/Scheduled/Published Workflow, Markdown und Media Uploads. Gebaut weil ich schon immer bloggen wollte, aber nie Zeit und kein Impressum hatte.
Stack: Python 3.8+, Flask, SQLAlchemy, MariaDB 10.5+, Bootstrap 5, Docker
Ich wollte immer einen eigenen Blog statt WordPress – leicht, selbst gehostet, ohne Overhead. Am Ende ist es nie live gegangen, weil Zeit gefehlt hat und in Deutschland ohne Impressum direkt Abmahn-Risiko hast. Deshalb liegt es jetzt als Open-Source hier.
- User Registrierung & Login
- Admin Content Verwaltung
- Post Workflow:
draft,scheduled,published,archived - Vorschau für unveröffentlichte Posts
- SEO-freundliche Slugs, Bootstrap Responsive UI
- Bild Uploads für Posts
app/– Flask App (Blueprints, Models, App Factory)templates/– Jinja2 Templatesstatic/– CSS & Uploadsmigrations/– DB Migrationen inkl.migrations/manual/SQLwsgi.py– WSGI EntrypointDockerfile/docker-compose.yml– Single Server Deploymentdocker-compose.enterprise.yml– Multi-Instance mit NGINX Loadbalancerdocker/– Container Helper & NGINX Config
- Docker Engine 24+
- Docker Compose v2+
cp .env.example .envMindestens setzen:
SECRET_KEYDB_PASSWORDDB_ROOT_PASSWORD
Ein ForgeCMS Container + ein MariaDB Container.
docker compose up -d --build- ForgeCMS:
http://localhost:8000 - Persistente Daten:
mariadb_dataunduploads_dataVolumes
Stop:
docker compose downZwei ForgeCMS Instanzen hinter NGINX + ein MariaDB.
docker compose -f docker-compose.enterprise.yml up -d --build- Einstieg:
http://localhost(Port 80) - Backend:
forgecms-a,forgecms-b - Shared Uploads Volume für beide Apps + NGINX
Stop:
docker compose -f docker-compose.enterprise.yml down- Container warten auf MariaDB bevor die App startet
- Migrationen laufen automatisch beim Start (im Enterprise Mode nur
forgecms-a) UPLOAD_FOLDERdefaultstatic/uploads, liegt im Volume
git clone <repo-url>
cd forgecms
python -m venv venv
source venv/bin/activate
pip install -r requirements.txtCREATE DATABASE forgecms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'forgecms'@'localhost' IDENTIFIED BY 'dein_passwort';
GRANT ALL PRIVILEGES ON forgecms.* TO 'forgecms'@'localhost';
FLUSH PRIVILEGES;cp .env.example .env
flask db upgrade
flask runLäuft auf http://127.0.0.1:5000.
flask shellfrom app import db
from app.models import User
admin = User(username='admin', email='admin@example.com', is_admin=True)
admin.set_password('sicheres-passwort')
db.session.add(admin)
db.session.commit()Für mich ist es die Basis für d5niel.de und den News-Bereich auf shadowunity.de – sobald Impressum geklärt ist. Kein WordPress, volle Kontrolle, MariaDB Erfahrung die ich eh täglich nutze. Und Docker-Ready für meinen "pure Docker statt Panel" Ansatz.