Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/backend/.env.prod.example
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ AZURE_CLIENT_ID=
AZURE_CLIENT_SECRET=
AZURE_TENANT_ID=

# File storage (Amazon S3, REQUIRED in production)
# Credentials of the IAM user that can read, write and delete objects in the bucket.
# Leave Storage__ServiceUrl unset: it is only for S3-compatible servers such as local MinIO.
S3_BUCKET_NAME=
S3_REGION=us-east-1
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

# Cache Settings
CACHE_ENABLED=true

Expand Down
13 changes: 11 additions & 2 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ BitFinance is a finance platform for tracking bills, expenses, organizations, an
- Durable in-app notifications and paid-plan bill reminder emails through Resend
- PostgreSQL persistence through Entity Framework Core
- Optional Redis caching
- Local object storage with MinIO and production S3-compatible storage
- Local object storage with MinIO and production storage on Amazon S3
- OpenAPI and Scalar API documentation

## Tech Stack
Expand Down Expand Up @@ -122,7 +122,16 @@ The local `.env.example` includes safe development defaults.
| `NOTIFICATIONS_FROM_ADDRESS` | Verified sender address | Development placeholder |
| `NOTIFICATIONS_FRONTEND_BASE_URL` | Base URL used by notification email links | `http://localhost:5174` |

Production deployments should use `.env.prod.example` as a template and provide real values for database credentials, JWT settings, Azure Key Vault configuration, and image tags.
Production deployments should use `.env.prod.example` as a template and provide real values for database credentials, JWT settings, Azure Key Vault configuration, file storage, and image tags.

### File storage

Attachments are stored through the S3 API. `Storage:ServiceUrl` selects the backend:

- **Set** (development): an S3-compatible server such as the local MinIO container, with path-style addressing and the `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` it is given.
- **Empty** (production): Amazon S3 in `Storage:Region`, with credentials from the default AWS chain (`AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` in the container).

In production, set `S3_BUCKET_NAME`, `S3_REGION`, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. The IAM user needs `s3:GetObject`, `s3:PutObject` and `s3:DeleteObject` on the bucket's objects. The database stores each object's key in `attachments.storage_path`, so moving files between buckets only requires copying them with the same keys.

## API Overview

Expand Down
4 changes: 4 additions & 0 deletions apps/backend/docker-compose.prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ services:
- AZURE_CLIENT_ID=${AZURE_CLIENT_ID}
- AZURE_CLIENT_SECRET=${AZURE_CLIENT_SECRET}
- AZURE_TENANT_ID=${AZURE_TENANT_ID}
- Storage__BucketName=${S3_BUCKET_NAME}
- Storage__Region=${S3_REGION}
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
- Notifications__EmailEnabled=${NOTIFICATIONS_EMAIL_ENABLED}
- Notifications__ResendApiToken=${RESEND_API_TOKEN}
- Notifications__ResendWebhookSecret=${RESEND_WEBHOOK_SECRET}
Expand Down
2 changes: 2 additions & 0 deletions docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ GitHub secrets used by the publish workflows:
Server-side requirements:

- `DEPLOY_PATH` contains `docker-compose.yml`, `docker-compose.prod.yml` and `.env`. Use `apps/backend/.env.prod.example` as the template for `.env`.
- The server's `.env` sets the S3 storage variables (`S3_BUCKET_NAME`, `S3_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`). See "File storage" in `apps/backend/README.md`.
- The deploy does not copy the compose files. After changing `docker-compose.yml` or `docker-compose.prod.yml`, copy them to `DEPLOY_PATH` yourself.
- The external Postgres volume (`POSTGRES_DATA_VOLUME`, default `bitfinance_postgres-data`) exists. See `apps/backend/README.md`.
- The SSH user can run `docker compose` and can write to `/var/www/bitfinance` without `sudo`.

Expand Down
Loading