# Shorefront A production-ready web application for managing [Shorewall](http://shorewall.net/) firewall configurations. ## Stack - **Backend:** Python 3.12, FastAPI, SQLAlchemy 2, Alembic, PostgreSQL 15 - **Frontend:** React 18, TypeScript, Vite, MUI v5, React Router v6, Axios - **Auth:** Keycloak (OIDC), JWT session cookie - **Infra:** Docker Compose (local dev), Helm + Kubernetes + Traefik (production) --- ## Quick Start (Docker Compose) ```bash # 1. Clone and enter the repo git clone shorefront && cd shorefront # 2. Start everything (postgres + backend + frontend) docker compose up --build # 3. Open http://localhost ``` Authentication is handled via Keycloak OIDC. You will be redirected to your Keycloak instance to log in. Your Keycloak user must be a member of the **firewall admins** group. --- ## Development (without Docker) **Backend:** ```bash cd backend python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt # Set environment variables export DATABASE_URL=postgresql://shorefront:changeme@localhost:5432/shorefront export JWT_SECRET_KEY=dev-secret export KEYCLOAK_URL=https://sso.example.com export KEYCLOAK_REALM=myrealm export KEYCLOAK_CLIENT_ID=shorefront export KEYCLOAK_CLIENT_SECRET= export KEYCLOAK_REDIRECT_URI=http://localhost:8000/auth/oidc/callback # Run migrations (creates schema + seed data) alembic upgrade head # Start the API server uvicorn app.main:app --reload # API available at http://localhost:8000 # Interactive docs at http://localhost:8000/docs ``` **Frontend:** ```bash cd frontend npm install npm run dev # Vite dev server at http://localhost:5173 # Proxies /api/* → http://localhost:8000 ``` --- ## First Steps After Login 1. Log in — you will be redirected to Keycloak. Your account must be in the **firewall admins** group. 2. A sample **homelab** config is pre-loaded with: - Zones: `fw` (firewall), `net` (ipv4), `loc` (ipv4) - Interface: `eth0` → zone `net` - Policies: loc→net ACCEPT, net→fw DROP, etc. - SNAT: `192.168.1.0/24` via `eth0` 3. Click **homelab** to open the Config Detail page. 4. Click **Generate Config** to preview or download the Shorewall files. 5. Create your own configs from the **Configurations** page. --- ## Generating Shorewall Files On the Config Detail page, click **Generate Config**: - **Preview:** File contents appear in a tabbed modal (zones / interfaces / policy / rules / snat) with copy-to-clipboard buttons. - **Download ZIP:** Downloads `-shorewall.zip` with all files ready to copy to `/etc/shorewall/`. --- ## Command-Line Download Each config has a **Download Token** — a secret string that allows downloading the generated ZIP without an active session. Useful for automation scripts and CI pipelines. ### Finding your token Open a config in the UI. The **Download Token** field is shown above the tabs. Click the copy icon to copy it. ### Downloading via curl ```bash curl -X POST "https:///api/configs//generate?format=zip" \ -H 'Content-Type: application/json' \ -d '{"token": ""}' \ -o shorewall.zip ``` Replace `` with the numeric ID visible in the URL when you open a config (e.g. `/configs/1`). ### Rotating the token Click the **Regenerate** button (⟳) next to the token field. The old token is immediately invalidated. Update any scripts that use it. --- ## API Documentation FastAPI generates interactive docs automatically: - **Swagger UI:** `http://localhost:8000/docs` - **ReDoc:** `http://localhost:8000/redoc` --- ## Kubernetes Deployment (Helm) ### Prerequisites - Kubernetes cluster with Traefik as the ingress controller - NFS share accessible at `192.168.17.199:/mnt/user/kubernetesdata/shorefront` - Keycloak instance with a `shorefront` client configured - Images available in the container registry (see CI/CD below) ### 1. Create Secrets Helm does **not** manage the Kubernetes secret. Run this once before the first deploy (and whenever credentials change): ```bash export POSTGRES_PASSWORD= export JWT_SECRET_KEY= export KEYCLOAK_CLIENT_SECRET= bash scripts/create-secrets.sh ``` This creates/updates the `shorefront-secret` Secret in the `shorefront` namespace. ### 2. Deploy ```bash helm upgrade --install shorefront ./helm/shorefront \ --namespace shorefront \ --create-namespace ``` Override values as needed (e.g. ingress host, Keycloak URL) via `--set` or a custom values file. ### 3. Verify Rollout ```bash kubectl rollout status deployment/backend -n shorefront kubectl rollout status deployment/frontend -n shorefront kubectl get ingress -n shorefront ``` ### Storage PostgreSQL data is persisted to `192.168.17.199:/mnt/user/kubernetesdata/shorefront` via a static NFS PersistentVolume. Ensure the NFS export is accessible from all cluster nodes before deploying. ### Uninstall ```bash helm uninstall shorefront -n shorefront # Note: PersistentVolume (Retain policy) and namespace are NOT deleted automatically. kubectl delete namespace shorefront kubectl delete pv shorefront-postgres-pv ``` --- ## CI/CD A Gitea Actions workflow (`.gitea/workflows/build-containers-on-demand.yml`) automatically builds and pushes images when `helm/shorefront/values.yaml`, `frontend/Dockerfile`, or `backend/Dockerfile` change. - Image tag is read from `containers.version` in `values.yaml` - Images are pushed to `git.baumann.gr/adebaumann/shorefront-{frontend,backend}:` - Requires a `REGISTRY_TOKEN` secret configured in Gitea **To release a new version:** bump `containers.version` in `values.yaml` and push. The workflow builds and pushes both images. Then run `helm upgrade` to deploy. --- ## Project Structure ``` shorefront/ ├── backend/ │ ├── Dockerfile │ ├── requirements.txt │ ├── alembic/ # DB migrations │ └── app/ │ ├── main.py # FastAPI app │ ├── models.py # SQLAlchemy ORM models │ ├── schemas.py # Pydantic schemas │ ├── auth.py # JWT + OIDC auth │ ├── shorewall_generator.py │ └── api/ # Route handlers │ ├── auth.py # OIDC login/callback/logout │ ├── configs.py # Config CRUD + generate │ ├── zones.py │ ├── interfaces.py │ ├── policies.py │ ├── rules.py │ ├── snat.py │ ├── hosts.py │ └── params.py ├── frontend/ │ ├── Dockerfile │ ├── nginx.conf │ └── src/ │ ├── api.ts # Axios API client │ ├── store/auth.ts # Auth state │ ├── routes/ # Page components │ └── components/ # Shared UI components ├── helm/shorefront/ # Kubernetes Helm chart ├── scripts/ │ └── create-secrets.sh # Creates k8s Secret before deploy ├── docker-compose.yml └── README.md ```