5.8 KiB
Deployment Guide
Local Development
Prerequisites
- Python 3.13+ (required by
pyproject.toml) - uv — Fast Python package manager
- Google Sheets API credentials (service account JSON)
Setup
git clone <repo-url>
cd fuj-management
# Install dependencies
uv sync
# Configure credentials
mkdir -p .secret
cp /path/to/credentials.json .secret/fuj-management-bot-credentials.json
# Optional: Set Fio API token for richer bank data
export FIO_API_TOKEN=your_token_here
# Start the web dashboard
make web
# → Flask server at http://localhost:5001
Makefile Targets
| Target | Command | Description |
|---|---|---|
help |
make help |
List all available targets |
venv |
make venv |
Sync virtual environment with pyproject.toml |
fees |
make fees |
Print fee calculation table |
match |
make match |
(Legacy) Direct bank matching |
web |
make web |
Start Flask dashboard on port 5001 |
sync |
make sync |
Sync last 30 days of bank transactions |
sync-2026 |
make sync-2026 |
Sync full year 2026 transactions |
infer |
make infer |
Auto-fill Person/Purpose in the sheet |
reconcile |
make reconcile |
Print CLI balance report |
test |
make test |
Run test suite |
test-v |
make test-v |
Run tests with verbose output |
image |
make image |
Build Docker image |
run |
make run |
Run Docker container locally |
The Makefile includes automatic venv management: targets that need Python depend on .venv/.last_sync, which triggers uv sync when pyproject.toml changes.
Docker Container
Building
make image
# → docker build -t fuj-management:latest -f build/Dockerfile .
Dockerfile Details
Base image: python:3.13-alpine
Build stages:
- Install system packages (
bash,tzdata) - Set timezone to
Europe/Prague - Install Python dependencies via pip
- Copy application files (
app.py,scripts/,templates/,Makefile) - Copy entrypoint script
Exposed port: 5001
Health check: wget -q -O /dev/null http://localhost:5001/ every 60s
Running Locally via Docker
make run
# → docker run -it --rm -p 5001:5001 fuj-management:latest
# With credentials and environment:
docker run -it --rm \
-p 5001:5001 \
-v $(pwd)/.secret:/app/.secret:ro \
-e FIO_API_TOKEN=your_token \
-e BANK_ACCOUNT=CZ8520100000002800359168 \
fuj-management:latest
Entrypoint
The build/entrypoint.sh script simply runs:
exec python3 /app/app.py
This uses Flask's built-in server directly. For a production deployment, consider adding gunicorn or waitress (noted as a TODO in the entrypoint).
Environment Variables
| Variable | Default | Description |
|---|---|---|
BANK_ACCOUNT |
CZ8520100000002800359168 |
IBAN for QR code generation |
FIO_API_TOKEN |
(none) | Fio REST API token |
PYTHONUNBUFFERED |
1 (set in Dockerfile) |
Ensures real-time log output |
CI/CD Pipeline
Gitea Actions
The project uses two Gitea Actions workflows:
1. Build and Push (build.yaml)
Triggers:
- Push of any tag
- Manual dispatch (with custom tag input)
Steps:
- Checkout code
- Login to Gitea container registry (
gitea.home.hrajfrisbee.cz) - Build Docker image using
build/Dockerfile - Push to
gitea.home.hrajfrisbee.cz/<owner>/<repo>:<tag>
Tag resolution: Uses the git tag name. For manual dispatch, uses the provided input.
2. Deploy to Kubernetes (kubernetes-deploy.yaml)
Triggers:
- Push to any branch
- Manual dispatch
Steps:
- Checkout code
- Install kubectl
- Retrieve Kanidm token from HashiCorp Vault:
- Authenticate to Vault via AppRole (
VAULT_ROLE_ID/VAULT_SECRET_ID) - Fetch API token from
secret/data/gitea/gitea-ci
- Authenticate to Vault via AppRole (
- Exchange API token for K8s OIDC token via Kanidm:
- POST to
https://idm.home.hrajfrisbee.cz/oauth2/token - Token exchange using
urn:ietf:params:oauth:grant-type:token-exchange
- POST to
- Configure kubectl with the OIDC token
- Run
kubectl auth whoamiandkubectl get ns(deploy commands are commented out — WIP)
Required secrets:
| Secret | Purpose |
|---|---|
REGISTRY_TOKEN |
Docker registry authentication |
VAULT_ROLE_ID |
HashiCorp Vault AppRole role ID |
VAULT_SECRET_ID |
HashiCorp Vault AppRole secret ID |
K8S_CA_CERT |
Kubernetes cluster CA certificate |
Infrastructure Topology
Gitea (git push / tag)
│
├── build.yaml → Docker Build → Gitea Container Registry
│ (gitea.home.hrajfrisbee.cz)
│
└── kubernetes-deploy.yaml → Vault → Kanidm → K8s Cluster
(192.168.0.31:6443)
This is a self-hosted infrastructure stack:
- Gitea for git hosting and CI/CD
- HashiCorp Vault for secret management
- Kanidm for identity/OIDC
- Kubernetes for container orchestration
Credentials Management
Google Sheets API
The system uses a Google Cloud service account for accessing the Payments Google Sheet. The credentials file must be:
- Stored at
.secret/fuj-management-bot-credentials.json - In Google Cloud service account JSON format
- The service account must be shared (as editor) on the target Google Sheet
For local development with OAuth2 (personal Google account), the system also supports the OAuth2 installed app flow — it will generate a token.pickle file on first use.
Fio Bank API
Optional. Set the FIO_API_TOKEN environment variable. The token is generated in Fio internetbanking under Settings → API.
Rate limit: 1 request per 30 seconds per token.
Deployment documentation generated from comprehensive code analysis on 2026-03-03.