Files
shorefront/README.md
Adrian A. Baumann 956f0c2cf5 docs: update README to reflect OIDC auth, secrets management, and CI/CD
Replace admin/admin credentials with Keycloak OIDC flow, fix Kubernetes
deploy section to use create-secrets.sh instead of --set secrets.*, add
CI/CD section, and update domain model references (masq→snat, new hosts/params).
2026-03-07 12:36:11 +01:00

7.0 KiB

Shorefront

A production-ready web application for managing Shorewall 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)

# 1. Clone and enter the repo
git clone <repo-url> 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:

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=<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:

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 <config-name>-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

curl -X POST "https://<host>/api/configs/<config-id>/generate?format=zip" \
  -H 'Content-Type: application/json' \
  -d '{"token": "<your-download-token>"}' \
  -o shorewall.zip

Replace <config-id> 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):

export POSTGRES_PASSWORD=<strong-password>
export JWT_SECRET_KEY=<strong-jwt-secret>
export KEYCLOAK_CLIENT_SECRET=<keycloak-client-secret>

bash scripts/create-secrets.sh

This creates/updates the shorefront-secret Secret in the shorefront namespace.

2. Deploy

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

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

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}:<version>
  • 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