2018-10-19 15:32:17 -04:00
# Open Accounting Server
2025-06-30 22:09:10 +12:00
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
2025-07-01 23:07:44 +12:00
- **Modular Storage**: S3-compatible attachment storage (Local, AWS S3, Backblaze B2, Cloudflare R2, MinIO)
2025-06-30 22:09:10 +12:00
- **Docker Ready**: Containerized deployment with multi-stage builds
- **SQLite Support**: Easy local development and testing
- **Security**: Environment variable support for sensitive data
2018-10-19 15:32:17 -04:00
## Prerequisites
2025-06-30 22:09:10 +12:00
- **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
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
# Run in development mode
just run-dev
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
# 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
```
2018-10-19 15:32:17 -04:00
## Configuration
2025-06-30 22:09:10 +12:00
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 |
2025-07-01 23:07:44 +12:00
#### 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)
2025-06-30 22:09:10 +12:00
⚠️ **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
```
2025-07-01 23:07:44 +12:00
#### 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
```
2025-06-30 22:09:10 +12:00
#### 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
2025-07-01 23:07:44 +12:00
# 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
2025-06-30 22:09:10 +12:00
```
## 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
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
# Or manually
OA_DATABASE_DRIVER=sqlite OA_PORT=8080 ./server
```
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
### Production
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
```bash
# With Docker Compose (recommended)
docker-compose up -d
2018-10-19 15:32:17 -04:00
2025-06-30 22:09:10 +12:00
# 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
```
2018-11-12 11:37:44 -05:00
2023-09-22 11:28:40 -06:00
## Docker
2025-06-30 22:09:10 +12:00
### 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 )
2023-09-22 11:28:40 -06:00
2025-06-30 22:09:10 +12:00
## License
2018-11-12 11:37:44 -05:00
2025-06-30 22:09:10 +12:00
See LICENSE file for details.