199 lines
5.8 KiB
Markdown
199 lines
5.8 KiB
Markdown
# Deployment Guide
|
|
|
|
## Local Development
|
|
|
|
### Prerequisites
|
|
|
|
- **Python 3.13+** (required by `pyproject.toml`)
|
|
- **[uv](https://docs.astral.sh/uv/)** — Fast Python package manager
|
|
- Google Sheets API credentials (service account JSON)
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
make image
|
|
# → docker build -t fuj-management:latest -f build/Dockerfile .
|
|
```
|
|
|
|
### Dockerfile Details
|
|
|
|
**Base image**: `python:3.13-alpine`
|
|
|
|
**Build stages**:
|
|
1. Install system packages (`bash`, `tzdata`)
|
|
2. Set timezone to `Europe/Prague`
|
|
3. Install Python dependencies via pip
|
|
4. Copy application files (`app.py`, `scripts/`, `templates/`, `Makefile`)
|
|
5. Copy entrypoint script
|
|
|
|
**Exposed port**: 5001
|
|
|
|
**Health check**: `wget -q -O /dev/null http://localhost:5001/` every 60s
|
|
|
|
### Running Locally via Docker
|
|
|
|
```bash
|
|
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:
|
|
```bash
|
|
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**:
|
|
1. Checkout code
|
|
2. Login to Gitea container registry (`gitea.home.hrajfrisbee.cz`)
|
|
3. Build Docker image using `build/Dockerfile`
|
|
4. 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**:
|
|
1. Checkout code
|
|
2. Install kubectl
|
|
3. 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`
|
|
4. 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`
|
|
5. Configure kubectl with the OIDC token
|
|
6. Run `kubectl auth whoami` and `kubectl 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.*
|