Ctrl K
ComunidadGuías…

DEPLOYMENT.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# Deployment Guide

This project supports multiple deployment strategies with modular CI/CD pipelines. Choose the approach that fits your infrastructure.

## Table of Contents

1. [Deployment Options](#deployment-options)
2. [Linux Service (systemd / OpenRC)](#linux-service-systemd--openrc)
3. [Windows Service](#windows-service)
4. [Docker Compose (GHCR)](#docker-compose-ghcr)
5. [Fly.io](#flyio)
6. [CI/CD Pipelines](#cicd-pipelines)
7. [Required Configuration](#required-configuration)

---

## Deployment Options

| Method | Best For | Pros | Cons |
|--------|----------|------|------|
| **Linux Service** | Bare-metal Linux, VPS, Alpine | Native, zero overhead, auto-restart, systemd + OpenRC | Linux only, manual updates |
| **Windows Service** | Windows desktop/server | Native, auto-rebuild on start, no visible window | Windows only, requires Go toolchain |
| **Docker Compose** | Self-hosted, VPS | Full control, customizable | Requires infrastructure management |
| **Fly.io** | Quick cloud deploy | Managed platform, auto-scaling | Costs for high usage |

All methods work with the same codebase and configuration files. Choose based on your infrastructure preferences.

---

## Linux Service (systemd / OpenRC)

The installer auto-detects the init system — systemd (most distros) or OpenRC (Alpine Linux). OpenRC support requires `supervise-daemon` (OpenRC >= 0.21).

### Quick Start

```bash
# 1. Clone and build
git clone https://github.com/Guliveer/twitch-miner-go.git
cd twitch-miner-go
./_run.sh  # builds the binary (Ctrl+C to stop after build)

# 2. Run the interactive installer
sudo ./tools/install-service.sh install
```

The wizard will ask for service name, paths, port, user, and optionally enable + start the service.

### Managing the Service

```bash
# Check status and recent logs (works with both init systems)
sudo ./tools/install-service.sh status

# systemd
systemctl status twitch-miner-go
systemctl restart twitch-miner-go
journalctl -u twitch-miner-go -f

# OpenRC (Alpine)
rc-service twitch-miner-go status
rc-service twitch-miner-go restart
tail -f /var/log/twitch-miner-go.log
```

### Uninstalling

```bash
sudo ./tools/install-service.sh uninstall
```

This stops and removes the service unit/init script. Binary, configs, and data are preserved — remove them manually if needed.

### File Locations (defaults)

| Item | Path |
|------|------|
| Binary | `/usr/local/bin/twitch-miner-go` |
| Configs | `/etc/twitch-miner-go/configs/` |
| Environment | `/etc/twitch-miner-go/.env` |
| Data (cookies) | `/var/lib/twitch-miner-go/` |
| Service (systemd) | `/etc/systemd/system/twitch-miner-go.service` |
| Service (OpenRC) | `/etc/init.d/twitch-miner-go` |
| Logs (OpenRC) | `/var/log/twitch-miner-go.log` |

---

## Windows Service

### Quick Start

```bat
REM Right-click tools\install-service.bat and select "Run as administrator"
tools\install-service.bat install
```

The wizard will ask for config directory, port, and log level. [NSSM](https://nssm.cc/) (Non-Sucking Service Manager) is auto-downloaded if not already installed.

### How It Works

The installer uses NSSM to wrap the application as a native Windows service. On every start (including automatic restarts after a crash), the service:

1. Rebuilds the binary from source (`go build`)
2. Launches the freshly built binary

### Config Editor & Tray in Service Mode

When running as a Windows service, the embedded config editor is still available
at **http://localhost:8070** in file mode (DB mode does not start it) — the
service binds it to `127.0.0.1` only, so you
can open it in a browser on the machine to manage account configs.

The system tray icon is **not** shown in service mode: Windows services run in a
non-interactive session (session 0) that has no desktop, so the tray cannot be
displayed there. This is a Windows platform limitation, not a bug — the miner
runs normally without it. Running with the `-no-tray` flag (as the service
installer does) is therefore the typical setup for service deployments.

This ensures config changes and code updates are always picked up without manual rebuilds.

### Managing the Service

```bat
tools\install-service.bat start       REM starts (triggers a rebuild first)
tools\install-service.bat stop
tools\install-service.bat restart     REM restart with a fresh rebuild
tools\install-service.bat status
```

### Uninstalling

```bat
tools\install-service.bat uninstall
```

This stops and removes the Windows service. The binary, configs, and logs are preserved — remove them manually if needed.

### File Locations (defaults)

| Item | Path |
|------|------|
| Binary | `<project-dir>\twitch-miner-go.exe` |
| Configs | `<project-dir>\configs\` |
| Service wrapper | `<project-dir>\_service-start.bat` |
| Logs | `<project-dir>\logs\service.log` |
| NSSM | `<project-dir>\tools\nssm\nssm.exe` |

### Prerequisites

- **Go toolchain** in the system PATH (not just user PATH — the service runs under the SYSTEM account)
- **Git** in the system PATH (for version embedding during builds)
- **Administrator privileges** to install/manage Windows services

---

## Docker Compose (GHCR)

### Quick Start (Docker)

```bash
# 1. Clone and configure
git clone https://github.com/Guliveer/twitch-miner-go.git
cd twitch-miner-go
cp .env.example .env
cp configs/example.yaml.example configs/your_username.yaml

# 2. Edit .env with required Twitch identifiers
nano .env  # Set TWITCH_CLIENT_ID_TV, TWITCH_CLIENT_ID_BROWSER, TWITCH_CLIENT_VERSION

# 3. Configure your account
nano configs/your_username.yaml

# 4. Start with Docker Compose
docker compose up -d

# 5. Check logs
docker compose logs -f
```

### Configuration (Docker)

The `docker-compose.yml` uses the published GHCR image by default:

```yaml
services:
  twitch-miner-go:
    image: ${TWITCH_MINER_IMAGE:-ghcr.io/guliveer/twitch-miner-go:latest}
```

#### Image Versions

Set `TWITCH_MINER_IMAGE` in `.env` to pin a specific version:

```bash
# Use latest (rolling)
TWITCH_MINER_IMAGE=ghcr.io/guliveer/twitch-miner-go:latest

# Use specific version
TWITCH_MINER_IMAGE=ghcr.io/guliveer/twitch-miner-go:1.6.0

# Use commit SHA
TWITCH_MINER_IMAGE=ghcr.io/guliveer/twitch-miner-go:sha-abc1234
```

#### Volume Mounts

- `./configs:/configs:ro` — Account configuration (read-only)
- `twitch-miner-data:/data` — Persistent cookies and state

#### Health Checks

The container includes automatic health checks:

```yaml
healthcheck:
  test: ["CMD", "/twitch-miner-go", "-healthcheck-url", "http://127.0.0.1:8080/health"]
  interval: 30s
  timeout: 10s
  retries: 3
  start_period: 15s
```

#### System Tray

Containers are headless — there is no desktop or DBus session for a system tray
icon to attach to. The image therefore ships with the tray disabled by default
(`NO_TRAY=true` is set in the `Dockerfile` and `docker-compose.yml`), and the
miner runs as a pure daemon. The embedded config editor remains available at
`http://127.0.0.1:8070` inside the container in file mode (DB mode does not
start it).

#### Updating

```bash
# Pull latest image
docker compose pull

# Restart with new image
docker compose up -d

# Clean up old images
docker image prune -f
```

---

## Fly.io

### Quick Start (Fly.io)

```bash
# 1. Install flyctl
curl -L https://fly.io/install.sh | sh

# 2. Login
fly auth login

# 3. Clone and configure
git clone https://github.com/Guliveer/twitch-miner-go.git
cd twitch-miner-go
cp configs/example.yaml.example configs/your_username.yaml

# 4. Configure your account
nano configs/your_username.yaml

# 5. Create app (first time only)
fly launch --no-deploy

# 6. Create persistent volume
fly volumes create miner_data --region fra --size 1

# 7. Set required Twitch runtime identifiers
fly secrets set TWITCH_CLIENT_ID_TV=your_tv_client_id
fly secrets set TWITCH_CLIENT_ID_BROWSER=your_browser_client_id
fly secrets set TWITCH_CLIENT_VERSION=your_client_version

# 8. (Optional) Set auth token for headless login
fly secrets set TWITCH_AUTH_TOKEN_YOUR_USERNAME=your_oauth_token

# 9. (Optional) Enable cookie encryption
# Generate a key first: ./tools/gen-cookie-key.sh
# fly secrets set COOKIE_ENCRYPTION_KEY=<generated_key>

# 10. Deploy
fly deploy
```

### Configuration (Fly.io)

The `fly.toml` includes optimized settings for the miner:

```toml
[env]
  PORT = '8080'
  DATA_DIR = '/data'
  GOMEMLIMIT = "400MiB"  # Memory limit for Go GC
  GOGC = "50"            # Aggressive GC for low-memory environment

[[vm]]
  cpu_kind = 'shared'
  cpus = 1
  memory_mb = 256        # Minimal footprint
```

#### Secrets Management

Fly.io uses encrypted secrets instead of `.env` files:

```bash
# Set secrets
fly secrets set KEY=VALUE

# List secrets (values hidden)
fly secrets list

# Remove secret
fly secrets unset KEY
```

#### Scaling

```bash
# Scale to multiple regions
fly scale count 2 --region fra,ams

# Change VM size
fly scale vm shared-cpu-1x --memory 512

# Auto-stop/start (cost optimization)
fly scale count 0  # Stop
fly scale count 1  # Start
```

#### Monitoring

```bash
# View logs
fly logs

# SSH into instance
fly ssh console

# Check status
fly status

# Open dashboard
fly open
```

---

## CI/CD Pipelines

The repository includes modular GitHub Actions workflows:

### Workflow Overview

| Workflow | Trigger | Purpose | Auto-runs |
|----------|---------|---------|-----------|
| **CI** ([ci.yml](.github/workflows/ci.yml)) | Push, PR | Test, lint, version bump | Always |
| **Docker Publish** ([docker-publish.yml](.github/workflows/docker-publish.yml)) | Push to main, tags | Build and push to GHCR | When enabled |
| **Fly.io Deploy** ([fly-deploy.yml](.github/workflows/fly-deploy.yml)) | Push to main, tags | Deploy to Fly.io | When `FLY_API_TOKEN` exists |

### Enabling Workflows

#### Docker Publish (GHCR)

**Auto-enabled** for public repositories. For private repos:

1. Go to repository Settings → Actions → General
2. Enable "Read and write permissions" for `GITHUB_TOKEN`
3. Workflow will run on next push to `main`

No additional configuration needed!

#### Fly.io Deploy

**Enabled when `FLY_API_TOKEN` secret is configured:**

1. Get your Fly.io API token:

   ```bash
   fly auth token
   ```

2. Add to GitHub:
   - Go to repository Settings → Secrets and variables → Actions
   - Click "New repository secret"
   - Name: `FLY_API_TOKEN`
   - Value: (paste your token)

3. Workflow will auto-run on next push to `main`

### Manual Triggers

Both workflows support manual dispatch:

```bash
# From GitHub UI: Actions → Select workflow → Run workflow

# Or via GitHub CLI:
gh workflow run docker-publish.yml
gh workflow run fly-deploy.yml
```

### Disabling Workflows

**To disable a workflow without deleting it:**

```bash
# Method 1: Remove trigger secret
# For Fly.io: delete FLY_API_TOKEN secret

# Method 2: Edit workflow file
# Change 'on:' section to only 'workflow_dispatch:'
on:
  workflow_dispatch:
```

---

## Required Configuration

### Twitch Runtime Identifiers

**Required for ALL deployment methods:**

| Variable | Description | How to Obtain |
|----------|-------------|---------------|
| `TWITCH_CLIENT_ID_TV` | TV app client ID | Inspect Twitch TV app traffic |
| `TWITCH_CLIENT_ID_BROWSER` | Browser client ID | DevTools Network tab → `gql` request header `Client-Id` |
| `TWITCH_CLIENT_VERSION` | Browser version | DevTools Network tab → `gql` request header `Client-Version` |

#### Getting Browser Values

1. Open <https://www.twitch.tv> in your browser
2. Open DevTools (F12) → Network tab
3. Filter for `gql`
4. Click any request to `https://gql.twitch.tv/gql`
5. Find Request Headers:
   - `Client-Id` → `TWITCH_CLIENT_ID_BROWSER`
   - `Client-Version` → `TWITCH_CLIENT_VERSION`

#### Getting TV Client ID

**Option 1:** Android TV emulator with traffic proxy
**Option 2:** Reuse existing TV client ID until Twitch invalidates it
**Option 3:** Check community resources for current IDs

### Account Configuration

Create one YAML file per account in `configs/`. The filename (without extension) becomes the username — no `username` field in the YAML:

```yaml
# configs/your_twitch_username.yaml
enabled: true

features:
  claim_drops_startup: false
  enable_analytics: true

max_watch_streams: 2

priority:
  - STREAK
  - DROPS
  - ORDER

streamers:
  - username: "streamer_name"
    settings:
      make_predictions: true
```

### Authentication

**Recommended:** Use auth tokens for headless environments

```bash
# Docker Compose (.env)
TWITCH_AUTH_TOKEN_YOUR_USERNAME=your_oauth_token

# Fly.io (secrets)
fly secrets set TWITCH_AUTH_TOKEN_YOUR_USERNAME=your_oauth_token
```

**Alternative:** Password (less reliable, may require 2FA)

```bash
TWITCH_PASSWORD_YOUR_USERNAME=your_password
```

**Interactive:** Device code flow (local development only)

---

## Comparison Matrix

| Feature | Docker Compose | Fly.io |
|---------|----------------|--------|
| **Cost** | Infrastructure cost only | ~$2-5/month (256MB VM) |
| **Setup Time** | 5 minutes | 5 minutes |
| **Maintenance** | Manual updates | Auto-deploy via CI/CD |
| **Scaling** | Manual | Automatic |
| **Monitoring** | External tools | Built-in dashboard |
| **Secrets** | `.env` file | Encrypted secrets |
| **Backup** | Volume backups | Volume snapshots |
| **Migration** | Portable containers | Vendor lock-in |

---

## Troubleshooting

### Troubleshooting: Docker Compose

**Container won't start:**

```bash
docker compose logs
# Check for missing Twitch identifiers
```

**Config changes not applied:**

```bash
docker compose down
docker compose up -d
```

**Old cookies causing issues:**

```bash
docker compose down
docker volume rm twitch-miner-go_twitch-miner-data
docker compose up -d
```

### Troubleshooting: Fly.io

**Deployment fails:**

```bash
fly logs
# Check for missing secrets
fly secrets list
```

**Out of memory:**

```bash
# Increase memory
fly scale vm shared-cpu-1x --memory 512
```

**Volume issues:**

```bash
fly volumes list
fly volumes destroy <volume_id>
fly volumes create miner_data --region fra --size 1
```

---

## Security Best Practices

1. **Never commit secrets** — use `.env` (gitignored) or secret managers
2. **Use auth tokens** instead of passwords when possible
3. **Enable dashboard auth** — set `DASHBOARD_USER` and `DASHBOARD_PASSWORD_SHA256`
4. **Rotate tokens** periodically
5. **Monitor logs** for authentication failures
6. **Use HTTPS** for external access (Fly.io includes this automatically)

---

## Next Steps

- **Configure notifications:** See [README.md](README.md#17-notifications)
- **Customize betting:** See [configs/example.yaml.example](configs/example.yaml.example)
- **Monitor performance:** Access dashboard at `http://localhost:8080` (Docker) or your Fly.io URL
- **Join community:** Check GitHub Discussions for tips and support