You've already forked openaccounting-server
forked from cybercinch/openaccounting-server
Consolidates storage backends into a single S3-compatible driver that supports: - AWS S3 (native) - Backblaze B2 (S3-compatible API) - Cloudflare R2 (S3-compatible API) - MinIO and other S3-compatible services - Local filesystem for development This replaces the previous separate B2 driver with a unified approach, reducing dependencies and complexity while adding support for more services. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
491 lines
13 KiB
Markdown
491 lines
13 KiB
Markdown
# Open Accounting Server
|
|
|
|
Open Accounting Server is a modern financial accounting system built with Go, featuring GORM integration, Viper configuration management, and Docker support.
|
|
|
|
## Features
|
|
|
|
- **GORM Integration**: Modern ORM with SQLite and MySQL support
|
|
- **Viper Configuration**: Flexible config management with environment variables
|
|
- **Modular Storage**: S3-compatible attachment storage (Local, AWS S3, Backblaze B2, Cloudflare R2, MinIO)
|
|
- **Docker Ready**: Containerized deployment with multi-stage builds
|
|
- **SQLite Support**: Easy local development and testing
|
|
- **Security**: Environment variable support for sensitive data
|
|
|
|
## Prerequisites
|
|
|
|
- **Go 1.24+** (updated from 1.8+)
|
|
- **SQLite** (for development) or **MySQL 5.7+** (for production)
|
|
- **Docker** (optional, for containerized deployment)
|
|
- **Just** (optional, for build automation)
|
|
|
|
## Quick Start
|
|
|
|
### Using Just (Recommended)
|
|
|
|
```bash
|
|
# Setup development environment
|
|
just dev-setup
|
|
|
|
# Run in development mode
|
|
just run-dev
|
|
|
|
# Build and run with Docker
|
|
just docker-run
|
|
```
|
|
|
|
### Manual Setup
|
|
|
|
```bash
|
|
# Install dependencies
|
|
go mod download
|
|
|
|
# Run with SQLite (development)
|
|
OA_DATABASE_DRIVER=sqlite ./server
|
|
|
|
# Run with MySQL (production)
|
|
OA_DATABASE_DRIVER=mysql OA_PASSWORD=secret ./server
|
|
```
|
|
|
|
## Configuration
|
|
|
|
The server now uses **Viper** for advanced configuration management with multiple sources:
|
|
|
|
### Configuration Sources (in order of precedence)
|
|
|
|
1. **Environment Variables** (highest priority)
|
|
2. **Config Files**: `config.json`, `config.yaml`, `config.toml`
|
|
3. **Default Values** (lowest priority)
|
|
|
|
### Config File Locations
|
|
|
|
- `./config.json` (current directory)
|
|
- `/etc/openaccounting/config.json`
|
|
- `~/.openaccounting/config.json`
|
|
|
|
### Environment Variables
|
|
|
|
All configuration can be overridden with environment variables using the `OA_` prefix:
|
|
|
|
| Environment Variable | Config Field | Default | Description |
|
|
|---------------------|--------------|---------|-------------|
|
|
| `OA_ADDRESS` | Address | `localhost` | Server bind address |
|
|
| `OA_PORT` | Port | `8080` | Server port |
|
|
| `OA_API_PREFIX` | ApiPrefix | `/api/v1` | API route prefix |
|
|
| `OA_DATABASE_DRIVER` | DatabaseDriver | `sqlite` | Database type: `sqlite` or `mysql` |
|
|
| `OA_DATABASE_FILE` | DatabaseFile | `./openaccounting.db` | SQLite database file |
|
|
| `OA_DATABASE_ADDRESS` | DatabaseAddress | `localhost:3306` | MySQL server address |
|
|
| `OA_DATABASE` | Database | | MySQL database name |
|
|
| `OA_USER` | User | | Database username |
|
|
| `OA_PASSWORD` | Password | | Database password ⚠️ |
|
|
| `OA_MAILGUN_DOMAIN` | MailgunDomain | | Mailgun domain |
|
|
| `OA_MAILGUN_KEY` | MailgunKey | | Mailgun API key ⚠️ |
|
|
| `OA_MAILGUN_EMAIL` | MailgunEmail | | Mailgun email |
|
|
| `OA_MAILGUN_SENDER` | MailgunSender | | Mailgun sender name |
|
|
|
|
#### Storage Configuration
|
|
|
|
| Environment Variable | Config Field | Default | Description |
|
|
|---------------------|--------------|---------|-------------|
|
|
| `OA_STORAGE_BACKEND` | Storage.Backend | `local` | Storage backend: `local` or `s3` |
|
|
|
|
**Local Storage**
|
|
| Environment Variable | Config Field | Default | Description |
|
|
|---------------------|--------------|---------|-------------|
|
|
| `OA_STORAGE_LOCAL_ROOTDIR` | Storage.Local.RootDir | `./uploads` | Root directory for file storage |
|
|
| `OA_STORAGE_LOCAL_BASEURL` | Storage.Local.BaseURL | | Base URL for serving files |
|
|
|
|
**S3-Compatible Storage** (AWS S3, Backblaze B2, Cloudflare R2, MinIO)
|
|
| Environment Variable | Config Field | Default | Description |
|
|
|---------------------|--------------|---------|-------------|
|
|
| `OA_STORAGE_S3_REGION` | Storage.S3.Region | | Region (use "auto" for Cloudflare R2) |
|
|
| `OA_STORAGE_S3_BUCKET` | Storage.S3.Bucket | | Bucket name |
|
|
| `OA_STORAGE_S3_PREFIX` | Storage.S3.Prefix | | Optional prefix for all objects |
|
|
| `OA_STORAGE_S3_ACCESSKEYID` | Storage.S3.AccessKeyID | | Access Key ID ⚠️ |
|
|
| `OA_STORAGE_S3_SECRETACCESSKEY` | Storage.S3.SecretAccessKey | | Secret Access Key ⚠️ |
|
|
| `OA_STORAGE_S3_ENDPOINT` | Storage.S3.Endpoint | | Custom endpoint (see examples below) |
|
|
| `OA_STORAGE_S3_PATHSTYLE` | Storage.S3.PathStyle | `false` | Use path-style addressing |
|
|
|
|
**S3-Compatible Service Endpoints:**
|
|
- **AWS S3**: Leave endpoint empty, set appropriate region
|
|
- **Backblaze B2**: `https://s3.us-west-004.backblazeb2.com` (replace region as needed)
|
|
- **Cloudflare R2**: `https://<account-id>.r2.cloudflarestorage.com`
|
|
- **MinIO**: `http://localhost:9000` (or your MinIO server URL)
|
|
|
|
⚠️ **Security**: Always use environment variables for sensitive data like passwords and API keys.
|
|
|
|
### Configuration Examples
|
|
|
|
#### Development (SQLite)
|
|
```bash
|
|
# Minimal - uses defaults
|
|
./server
|
|
|
|
# Custom database file and port
|
|
OA_DATABASE_FILE=./dev.db OA_PORT=9090 ./server
|
|
```
|
|
|
|
#### Production (MySQL)
|
|
```bash
|
|
# With environment variables (recommended)
|
|
export OA_DATABASE_DRIVER=mysql
|
|
export OA_DATABASE_ADDRESS=db.example.com:3306
|
|
export OA_DATABASE=openaccounting_prod
|
|
export OA_USER=openaccounting
|
|
export OA_PASSWORD=secure_password
|
|
export OA_MAILGUN_KEY=key-abc123
|
|
./server
|
|
|
|
# Or inline
|
|
OA_DATABASE_DRIVER=mysql OA_PASSWORD=secret OA_MAILGUN_KEY=key-123 ./server
|
|
```
|
|
|
|
#### Storage Configuration Examples
|
|
```bash
|
|
# Local storage (default)
|
|
export OA_STORAGE_BACKEND=local
|
|
export OA_STORAGE_LOCAL_ROOTDIR=./uploads
|
|
./server
|
|
|
|
# AWS S3
|
|
export OA_STORAGE_BACKEND=s3
|
|
export OA_STORAGE_S3_REGION=us-west-2
|
|
export OA_STORAGE_S3_BUCKET=my-app-attachments
|
|
export OA_STORAGE_S3_ACCESSKEYID=your-access-key
|
|
export OA_STORAGE_S3_SECRETACCESSKEY=your-secret-key
|
|
./server
|
|
|
|
# Backblaze B2 (S3-compatible)
|
|
export OA_STORAGE_BACKEND=s3
|
|
export OA_STORAGE_S3_REGION=us-west-004
|
|
export OA_STORAGE_S3_BUCKET=my-app-attachments
|
|
export OA_STORAGE_S3_ACCESSKEYID=your-b2-key-id
|
|
export OA_STORAGE_S3_SECRETACCESSKEY=your-b2-application-key
|
|
export OA_STORAGE_S3_ENDPOINT=https://s3.us-west-004.backblazeb2.com
|
|
export OA_STORAGE_S3_PATHSTYLE=true
|
|
./server
|
|
|
|
# Cloudflare R2
|
|
export OA_STORAGE_BACKEND=s3
|
|
export OA_STORAGE_S3_REGION=auto
|
|
export OA_STORAGE_S3_BUCKET=my-app-attachments
|
|
export OA_STORAGE_S3_ACCESSKEYID=your-r2-access-key
|
|
export OA_STORAGE_S3_SECRETACCESSKEY=your-r2-secret-key
|
|
export OA_STORAGE_S3_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
|
|
./server
|
|
|
|
# MinIO (self-hosted)
|
|
export OA_STORAGE_BACKEND=s3
|
|
export OA_STORAGE_S3_REGION=us-east-1
|
|
export OA_STORAGE_S3_BUCKET=my-app-attachments
|
|
export OA_STORAGE_S3_ACCESSKEYID=minioadmin
|
|
export OA_STORAGE_S3_SECRETACCESSKEY=minioadmin
|
|
export OA_STORAGE_S3_ENDPOINT=http://localhost:9000
|
|
export OA_STORAGE_S3_PATHSTYLE=true
|
|
./server
|
|
```
|
|
|
|
#### Docker
|
|
```bash
|
|
# SQLite with volume mount
|
|
docker run -p 8080:8080 \
|
|
-e OA_DATABASE_DRIVER=sqlite \
|
|
-v ./data:/app/data \
|
|
openaccounting-server:latest
|
|
|
|
# MySQL with environment variables
|
|
docker run -p 8080:8080 \
|
|
-e OA_DATABASE_DRIVER=mysql \
|
|
-e OA_DATABASE_ADDRESS=mysql:3306 \
|
|
-e OA_PASSWORD=secret \
|
|
openaccounting-server:latest
|
|
|
|
# With AWS S3 storage
|
|
docker run -p 8080:8080 \
|
|
-e OA_STORAGE_BACKEND=s3 \
|
|
-e OA_STORAGE_S3_REGION=us-west-2 \
|
|
-e OA_STORAGE_S3_BUCKET=my-attachments \
|
|
-e OA_STORAGE_S3_ACCESSKEYID=your-key \
|
|
-e OA_STORAGE_S3_SECRETACCESSKEY=your-secret \
|
|
openaccounting-server:latest
|
|
|
|
# With Cloudflare R2 storage
|
|
docker run -p 8080:8080 \
|
|
-e OA_STORAGE_BACKEND=s3 \
|
|
-e OA_STORAGE_S3_REGION=auto \
|
|
-e OA_STORAGE_S3_BUCKET=my-attachments \
|
|
-e OA_STORAGE_S3_ACCESSKEYID=your-r2-key \
|
|
-e OA_STORAGE_S3_SECRETACCESSKEY=your-r2-secret \
|
|
-e OA_STORAGE_S3_ENDPOINT=https://account-id.r2.cloudflarestorage.com \
|
|
openaccounting-server:latest
|
|
```
|
|
|
|
## Database Setup
|
|
|
|
### SQLite (Development)
|
|
|
|
SQLite databases are created automatically. No manual setup required.
|
|
|
|
```bash
|
|
# Uses ./openaccounting.db by default
|
|
OA_DATABASE_DRIVER=sqlite ./server
|
|
|
|
# Custom location
|
|
OA_DATABASE_DRIVER=sqlite OA_DATABASE_FILE=./data/myapp.db ./server
|
|
```
|
|
|
|
### MySQL (Production)
|
|
|
|
Use the provided schema files to create your MySQL database:
|
|
|
|
```sql
|
|
-- Create database and user
|
|
CREATE DATABASE openaccounting;
|
|
CREATE USER 'openaccounting'@'%' IDENTIFIED BY 'secure_password';
|
|
GRANT ALL PRIVILEGES ON openaccounting.* TO 'openaccounting'@'%';
|
|
```
|
|
|
|
The server will automatically create tables and run migrations on startup.
|
|
|
|
## Building
|
|
|
|
### Local Build
|
|
|
|
```bash
|
|
# Development build
|
|
go build -o server ./core/
|
|
|
|
# Production build (optimized)
|
|
CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -ldflags="-w -s" -o server ./core/
|
|
```
|
|
|
|
### Docker Build
|
|
|
|
```bash
|
|
# Build image
|
|
docker build -t openaccounting-server:latest .
|
|
|
|
# Multi-platform build
|
|
docker buildx build --platform linux/amd64,linux/arm64 -t openaccounting-server:latest .
|
|
```
|
|
|
|
## Running
|
|
|
|
### Development
|
|
|
|
```bash
|
|
# Local with SQLite
|
|
just run-dev
|
|
|
|
# Or manually
|
|
OA_DATABASE_DRIVER=sqlite OA_PORT=8080 ./server
|
|
```
|
|
|
|
### Production
|
|
|
|
```bash
|
|
# With Docker Compose (recommended)
|
|
docker-compose up -d
|
|
|
|
# Or manually with environment file
|
|
export $(cat .env | xargs)
|
|
./server
|
|
```
|
|
|
|
## Just Recipes
|
|
|
|
This project includes a `justfile` with common tasks:
|
|
|
|
```bash
|
|
just --list # Show all available recipes
|
|
just build # Build the application
|
|
just run-dev # Run in development mode
|
|
just docker-build # Build Docker image
|
|
just docker-run # Run container
|
|
just test # Run tests
|
|
just config-help # Show configuration help
|
|
just dev-setup # Complete development setup
|
|
```
|
|
|
|
## API
|
|
|
|
The server provides a REST API at `/api/v1/` (configurable via `OA_API_PREFIX`).
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
curl http://localhost:8080/api/v1/health
|
|
```
|
|
|
|
## Development
|
|
|
|
### Prerequisites
|
|
|
|
```bash
|
|
# Install Go dependencies
|
|
go mod download
|
|
|
|
# Install development tools (optional)
|
|
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
|
```
|
|
|
|
### Running Tests
|
|
|
|
```bash
|
|
just test
|
|
# or
|
|
go test ./...
|
|
```
|
|
|
|
### Code Quality
|
|
|
|
```bash
|
|
# Format code
|
|
just fmt
|
|
|
|
# Lint code (requires golangci-lint)
|
|
just lint
|
|
```
|
|
|
|
## Docker
|
|
|
|
### Official Images
|
|
|
|
Docker images are available with multi-stage builds for optimal size and security:
|
|
|
|
- Non-root user for security
|
|
- Alpine Linux base for minimal attack surface
|
|
- Health checks included
|
|
- Volume support for data persistence
|
|
|
|
### Environment Variables in Docker
|
|
|
|
```dockerfile
|
|
ENV OA_DATABASE_DRIVER=sqlite \
|
|
OA_DATABASE_FILE=/app/data/openaccounting.db \
|
|
OA_ADDRESS=0.0.0.0 \
|
|
OA_PORT=8080
|
|
```
|
|
|
|
### Data Persistence
|
|
|
|
```bash
|
|
# Mount volume for SQLite data
|
|
docker run -v ./data:/app/data openaccounting-server:latest
|
|
|
|
# Use named volume
|
|
docker volume create openaccounting-data
|
|
docker run -v openaccounting-data:/app/data openaccounting-server:latest
|
|
```
|
|
|
|
## Deployment
|
|
|
|
### Docker Compose
|
|
|
|
```yaml
|
|
version: '3.8'
|
|
services:
|
|
openaccounting:
|
|
image: openaccounting-server:latest
|
|
ports:
|
|
- "8080:8080"
|
|
environment:
|
|
OA_DATABASE_DRIVER: mysql
|
|
OA_DATABASE_ADDRESS: mysql:3306
|
|
OA_DATABASE: openaccounting
|
|
OA_USER: openaccounting
|
|
OA_PASSWORD: ${DB_PASSWORD}
|
|
depends_on:
|
|
- mysql
|
|
|
|
mysql:
|
|
image: mysql:8.0
|
|
environment:
|
|
MYSQL_DATABASE: openaccounting
|
|
MYSQL_USER: openaccounting
|
|
MYSQL_PASSWORD: ${DB_PASSWORD}
|
|
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
|
|
volumes:
|
|
- mysql_data:/var/lib/mysql
|
|
|
|
volumes:
|
|
mysql_data:
|
|
```
|
|
|
|
### Kubernetes
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: openaccounting-server
|
|
spec:
|
|
replicas: 3
|
|
selector:
|
|
matchLabels:
|
|
app: openaccounting-server
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: openaccounting-server
|
|
spec:
|
|
containers:
|
|
- name: openaccounting-server
|
|
image: openaccounting-server:latest
|
|
ports:
|
|
- containerPort: 8080
|
|
env:
|
|
- name: OA_DATABASE_DRIVER
|
|
value: "mysql"
|
|
- name: OA_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: openaccounting-secrets
|
|
key: db-password
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **Config file not found**: The server will use environment variables and defaults if no config file is found
|
|
2. **Database connection failed**: Check your database credentials and connectivity
|
|
3. **Permission denied**: Ensure proper file permissions for SQLite database files
|
|
|
|
### Debug Mode
|
|
|
|
```bash
|
|
# Enable verbose logging
|
|
OA_LOG_LEVEL=debug ./server
|
|
|
|
# Check configuration
|
|
just config-help
|
|
```
|
|
|
|
### Health Checks
|
|
|
|
```bash
|
|
# Application health
|
|
curl http://localhost:8080/api/v1/health
|
|
|
|
# Docker health check
|
|
docker inspect --format='{{.State.Health.Status}}' container_name
|
|
```
|
|
|
|
## Migration from Legacy Setup
|
|
|
|
The server maintains backward compatibility with existing `config.json` files while adding Viper features:
|
|
|
|
1. Existing `config.json` files continue to work
|
|
2. Add environment variables for sensitive data
|
|
3. Use SQLite for easier local development
|
|
4. Leverage Docker for production deployments
|
|
|
|
## Help & Support
|
|
|
|
- **Documentation**: This README and inline code comments
|
|
- **Issues**: GitHub Issues for bug reports and feature requests
|
|
- **Community**: [Join our Slack chatroom](https://join.slack.com/t/openaccounting/shared_invite/zt-23zy988e8-93HP1GfLDB7osoQ6umpfiA)
|
|
|
|
## License
|
|
|
|
See LICENSE file for details. |