# 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://.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.