docs: Phase 5 - Comprehensive deployment documentation

- Created detailed srv/README.md with:
  - Quick start guide
  - SystemD service setup instructions
  - Reverse proxy configuration (Caddy & Nginx)
  - Complete API endpoint reference
  - Client configuration examples
  - Troubleshooting guide
  - Security considerations
  - Future enhancement roadmap
- Updated main README.md with server & sync features
- Added sync command quick reference
- Documented offline support and conflict resolution
This commit is contained in:
2026-01-05 16:21:09 +01:00
parent 40c09d6a8a
commit 4c54814eb5
2 changed files with 416 additions and 10 deletions
+365 -9
View File
@@ -1,12 +1,368 @@
# Server
Opal-task is now a great task CLI management tool, however I need my task list available elsewhere. For reading, yes, but also modification.
# Opal-Task Server
## Current infrastructure
I host a VPS behind a Caddy reverse proxy. It hosts an authentik instance for SSO to my services.
Opal-task server provides a REST API for syncing tasks across multiple devices. This enables household task sharing and access from anywhere.
## Usecase
- Use within household to share tasks or filters. For our first version we should use one task database and share all data. This might branch off to sharing with access control (sharing specific tags/projects for instance)
- CRUD tasks on the go
## Features
## Implementation
I was thinking of hosting an api, then building a minimal svelte-kit frontend that could be used as a PWA on our devices. What are your thoughts? We could use oauth for authentication through authentik. for now disregard the front-end implementation.
- **REST API** - Chi-based HTTP API for task management
- **API Key Authentication** - Secure authentication using bcrypt-hashed keys
- **Bidirectional Sync** - Push and pull changes with conflict resolution
- **Offline Support** - Queue changes when server is unreachable
- **Change Tracking** - Automatic change log with configurable retention
- **Single Database** - Shared household task database (v1)
## Quick Start
### 1. Build the Binary
```bash
cd opal-task
go build -o opal main.go
```
### 2. Generate API Key
On your server (with direct database access):
```bash
./opal server keygen --name "My Device" --db /var/lib/opal/opal.db
```
Output:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
API Key Generated Successfully
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Name: My Device
Key: oak_abc123...
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ IMPORTANT: Save this key securely!
It will not be displayed again.
```
### 3. Start the Server
```bash
./opal server start --addr :8080 --db /var/lib/opal/opal.db
```
### 4. Configure Client
On your local machine or phone:
```bash
opal sync init --url https://opal.yourdomain.com --key oak_abc123...
```
Or use interactive mode:
```bash
opal sync init
# Enter server URL: https://opal.yourdomain.com
# Enter API key: oak_abc123...
```
### 5. Sync Your Tasks
```bash
# Full bidirectional sync
opal sync now
# Push local changes only
opal sync up
# Pull server changes only
opal sync down
# Initial merge (for existing local database)
opal sync merge --prefer-local
```
## Server Deployment
### Option 1: SystemD Service (Recommended)
**1. Install Binary**
```bash
# Build
go build -o opal main.go
# Copy to system location
sudo cp opal /usr/local/bin/
# Create data directory
sudo mkdir -p /var/lib/opal
sudo chown $USER:$USER /var/lib/opal
```
**2. Generate First API Key**
```bash
opal server keygen --name "Admin" --db /var/lib/opal/opal.db
# Save the generated key!
```
**3. Create SystemD Service**
Create `/etc/systemd/system/opal.service`:
```ini
[Unit]
Description=Opal Task API Server
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/var/lib/opal
ExecStart=/usr/local/bin/opal server start --addr :8080 --db /var/lib/opal/opal.db
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
```
**4. Enable and Start Service**
```bash
sudo systemctl daemon-reload
sudo systemctl enable opal
sudo systemctl start opal
sudo systemctl status opal
```
### Option 2: Direct Execution
```bash
# Run in background
nohup ./opal server start --addr :8080 --db /var/lib/opal/opal.db > opal.log 2>&1 &
```
## Reverse Proxy Setup
### Caddy (Recommended)
Add to your Caddyfile:
```
opal.yourdomain.com {
reverse_proxy localhost:8080
}
```
Reload Caddy:
```bash
sudo systemctl reload caddy
```
### Nginx
```nginx
server {
listen 443 ssl http2;
server_name opal.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
## API Endpoints
### Authentication
All endpoints (except `/health`) require authentication via API key:
```
Authorization: Bearer oak_abc123...
```
### Health Check
```
GET /health
```
Returns server status.
### Tasks
```
GET /tasks - List tasks (with filters)
GET /tasks/{uuid} - Get specific task
POST /tasks - Create task
PUT /tasks/{uuid} - Update task
DELETE /tasks/{uuid} - Delete task
POST /tasks/{uuid}/complete - Mark task complete
POST /tasks/{uuid}/start - Start task
POST /tasks/{uuid}/stop - Stop task
```
**Query Parameters for GET /tasks:**
- `status` - pending, completed, deleted
- `project` - Project name
- `priority` - L, M, H, D
- `tag` - Tag name (can specify multiple)
### Tags
```
GET /tasks/{uuid}/tags - Get task tags
POST /tasks/{uuid}/tags - Add tag
DELETE /tasks/{uuid}/tags/{tag} - Remove tag
GET /tags - List all tags
```
### Projects
```
GET /projects - List all projects
```
### Sync
```
POST /sync/changes - Get changes since timestamp
POST /sync/push - Push local changes
```
### API Keys
```
GET /auth/keys - List API keys
DELETE /auth/keys/{id} - Revoke API key
```
## Client Configuration
Sync settings are stored in `~/.config/jade/opal.yml`:
```yaml
# Task settings
default_filter: status:pending
default_sort: due,priority
color_output: true
week_start_day: monday
default_due_time: ""
# Sync settings
sync_enabled: true
sync_url: https://opal.yourdomain.com
sync_api_key: oak_abc123...
sync_client_id: 550e8400-e29b-41d4-a716-446655440000
sync_strategy: last-write-wins
sync_queue_offline: true
```
## Sync Strategies
- **last-write-wins** (default) - Most recently modified version wins
- **server-wins** - Server version always wins
- **client-wins** - Client version always wins
## Change Log Retention
By default, the change log retains entries for 30 days. This can be configured in the database:
```sql
UPDATE sync_config SET value = '60' WHERE key = 'change_log_retention_days';
```
Or programmatically:
```go
engine.SetChangeLogRetentionDays(60)
```
Cleanup runs manually or can be scheduled:
```bash
# In your cron or systemd timer
./opal server cleanup --db /var/lib/opal/opal.db
```
## Troubleshooting
### Server won't start
- Check if port 8080 is already in use: `sudo lsof -i :8080`
- Verify database path exists and is writable
- Check logs: `journalctl -u opal -f`
### Client can't connect
- Test server health: `curl https://opal.yourdomain.com/health`
- Verify API key is correct
- Check firewall allows traffic on port 8080
- Ensure reverse proxy is properly configured
### Sync conflicts
- View conflict log: `opal sync log`
- Conflicts are automatically resolved based on strategy
- By default, last-write-wins is used
### Offline changes not syncing
- Check queue status: `opal sync status`
- Verify `sync_queue_offline: true` in config
- Clear queue if needed: Delete `~/.config/jade/sync_queue.json`
## Database Schema
### Core Tables
- `tasks` - Main task storage
- `tags` - Task tags (many-to-many)
- `working_set` - Display ID mapping (client-local)
### Sync Tables
- `users` - User accounts (currently single shared user)
- `api_keys` - Authentication keys
- `sync_state` - Per-client sync state
- `change_log` - Change tracking (key:value format)
- `sync_config` - Server configuration
## Security Considerations
- API keys are hashed with bcrypt before storage
- Never log full API keys
- Use HTTPS in production (via reverse proxy)
- Implement rate limiting for production use
- Backup database regularly
- Rotate API keys periodically
## Future Enhancements
- OAuth2 with Authentik for web/mobile clients
- Per-user task separation with sharing
- Real-time sync via WebSockets
- Web/mobile frontend (SvelteKit PWA)
- Access control (share specific tags/projects)
- Audit logging
- Database backup automation
## Support
For issues or questions:
- Check logs: `journalctl -u opal -f`
- View sync status: `opal sync status`
- View conflicts: `opal sync log`
- Test connectivity: `curl https://opal.yourdomain.com/health`
## License
Same as opal-task main project.