# ots service Command Design - December 2024

## Overview

Design for managing systemd template services (e.g., `valkey-server@.service`) on Debian 13 systems. Uses package-provided templates rather than custom unit files.

## Command Structure

```bash
ots service init valkey 6379       # Full setup wizard
ots service enable valkey 6380     # Add another instance
ots service disable valkey 6379    # Stop/disable instance
ots service status valkey 6379     # Show systemd status
ots service logs valkey 6379       # journalctl wrapper
ots service list valkey            # Auto-discover instances
ots service doctor valkey 6379     # Comprehensive health check
ots service reconcile valkey       # Detect DB vs systemctl drift
ots service adopt valkey 6379      # Bring manual units under management
ots service forget valkey 6379     # Remove phantom DB records
ots service secret-set valkey 6379 requirepass
ots service secret-rotate valkey 6379 requirepass
```

## Key Design Decisions

### 1. Config File Management
- **Strategy**: Copy-on-write with `/etc/<pkg>/instances/` subdirectory
- Avoids dpkg conffile conflicts on package upgrades
- Package base config (`/etc/valkey/valkey.conf`) treated as readonly reference

### 2. Source of Truth
- **systemctl** = runtime state (is-active, is-enabled, list-units)
- **SQLite database** = metadata (config paths, ports, timestamps, audit trail)
- Use `systemctl --output=json` on Debian 13 (systemd 255+) for robustness

### 3. Secret Handling (Three Tiers)
- **inline**: Secrets in main config (mode 0600)
- **separate** (default): `.conf` + `.secrets` files
- **credential**: systemd LoadCredential= directive

### 4. FHS Compliance
- Config: `/etc/<pkg>/instances/{instance}.conf`
- Secrets: `/etc/<pkg>/instances/{instance}.secrets` (mode 0600)
- Data: `/var/lib/<pkg>/{instance}/`

## Database Schema

```sql
service_instances (package, instance, config_file, data_dir, port, created_at)
service_actions (timestamp, package, instance, action, success, notes)
```

## ServicePackage Registry Pattern

```python
@dataclass
class SecretConfig:
    secret_keys: list[str]
    secrets_file_pattern: str | None
    include_directive: str | None
    config_with_secrets_mode: int = 0o600
    secrets_file_mode: int = 0o600
    secrets_owned_by_service: bool = True

@dataclass
class ServicePackage:
    name: str
    template: str                    # e.g., "valkey-server@"
    config_dir: Path                 # /etc/valkey
    data_dir: Path                   # /var/lib/valkey
    config_file_pattern: str         # "{instance}.conf"
    default_service: str | None      # "valkey-server.service"
    default_config: Path | None      # /etc/valkey/valkey.conf
    secrets: SecretConfig | None
    # ... additional fields
```

## Doctor Command Checks

1. `systemd_syntax` - systemd-analyze verify
2. `security_score` - systemd-analyze security
3. `config_file` - exists, correct permissions
4. `secrets_file` - 0600, correct ownership
5. `data_directory` - exists, correct ownership
6. `runtime_status` - active + enabled
7. `db_sync` - DB matches systemctl

## File Structure

```
src/ots_containers/commands/service/
    __init__.py
    app.py           # Main commands
    packages.py      # ServicePackage registry
    _helpers.py      # Config/secret helpers
    db.py            # Database operations (extend existing)
```

## Ops Standards Review Result

- ✅ FHS Compliance: 10/10
- ✅ systemd Integration: 9/10
- ⚠️ Security: Addressed with secret handling
- ✅ Maintainability: 9/10 (reconcile/adopt pattern)

## Related Memories
- fhs-directory-standards (comprehensive FHS research)
