# Deploying GrokwayV2 to Production

This guide explains how to deploy the **GrokwayV2 Server** using Docker and Docker Compose.

## Prerequisites

- A Linux server (Ubuntu/Debian recommended) with a public IP.
- **Docker** and **Docker Compose** installed.
- A domain name (e.g., `example.com`) pointing to your server's IP.
- **Wildcard DNS** configured (e.g., `*.example.com` -> Server IP) to support dynamic subdomains.

## 1. Installation

1. **Clone the repository** (or copy the files) to your server:
   ```bash
   git clone <repository-url>
   cd GrokwayV2
   ```

2. **Verify Configuration**
   - Ensure `Dockerfile` and `docker-compose.yml` are present.
   - The default configuration uses ports `2222` (SSH) and `8080` (HTTP). Open these ports in your firewall (e.g., Security Groups, UFW).

## 2. Deploy with Docker Compose

Run the following command to build and start the server in detached mode:

```bash
docker-compose up -d --build
```

### Verify Status
Check if the container is running:
```bash
docker-compose ps
```

Check logs:
```bash
docker-compose logs -f
```

## 3. Client Connection

Clients can now connect to your server using the public IP or domain.

**Command:**
```bash
# If running locally (dev)
go run cmd/client/main.go --server example.com:2222 --local <local-port>

# If using a compiled binary
./grokway-client --server example.com:2222 --local <local-port>
```

> **Note:** Ensure the client points to port `2222` (or your mapped SSH port).

## 4. Updates

To deploy a new version:

1. Pull the latest code:
   ```bash
   git pull origin main
   ```
2. Rebuild and restart:
   ```bash
   docker-compose up -d --build
   ```

## Troubleshooting

- **Connection Refused:** Check if ports 2222 and 8080 are open in the firewall.
- **DNS Issues:** Ensure your wildcard DNS (`*.example.com`) is correctly propagating.
- **Permission Denied:** Ensure your user has rights to run docker commands (add user to docker group).

## Nginx Configuration

Since you already have `api.orin.remote.band` configured, you can add a new configuration for the main application and its subdomains.

### 1. HTTP/HTTPS Configuration (sites-available)

Create a new file `/etc/nginx/sites-available/grokway`:

```nginx
server {
    # Main domain and wildcard subdomains
    server_name grokway.orin.remote.band *.grokway.orin.remote.band;
    
    location / {
        proxy_pass http://127.0.0.1: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;
        
        # WebSocket support (important for future interactive features)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    listen 80;
}
```

Enable it:
```bash
ln -s /etc/nginx/sites-available/grokway /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
```

**SSL Certificate (Crucial Step):**

To support dynamic subdomains (e.g., `client1.grokway.orin.remote.band`), you **MUST** obtain a **Wildcard Certificate**. A standard certificate for `grokway.orin.remote.band` is **NOT valid** for its subdomains.

You need a certificate that covers both:
1. `grokway.orin.remote.band`
2. `*.grokway.orin.remote.band`

**How to get a Wildcard Certificate with Certbot:**
Wildcard certificates require **DNS validation** (you cannot use HTTP validation).

```bash
# Request a wildcard certificate
sudo certbot certonly --manual --preferred-challenges dns -d "grokway.orin.remote.band" -d "*.grokway.orin.remote.band"
```

1. Run the command.
2. Certbot will ask you to create a specific **TXT record** in your DNS provider (where you manage `orin.remote.band`).
3. Create the TXT record as instructed.
4. Wait a minute for propagation, then press Enter.

Once obtained, update your Nginx config (`/etc/nginx/sites-available/grokway`) to use the new certificates.

**Full Configuration with SSL:**

```nginx
server {
    server_name grokway.orin.remote.band *.grokway.orin.remote.band;

    # SSL Configuration
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/grokway.orin.remote.band/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/grokway.orin.remote.band/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass http://127.0.0.1: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;
        
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

# Redirect HTTP to HTTPS
server {
    if ($host = grokway.orin.remote.band) {
        return 301 https://$host$request_uri;
    }
    # Also redirect subdomains if needed, or use a wildcard match here

    listen 80;
    server_name grokway.orin.remote.band *.grokway.orin.remote.band;
    return 404;
}
```

### 2. SSH Proxy Configuration (nginx.conf)

**Important:** The SSH proxy uses the `stream` module. This block **CANNOT** go inside `sites-available` (which are included inside the `http` block). It must go at the top level of `/etc/nginx/nginx.conf`.

Edit `/etc/nginx/nginx.conf` and add this **at the very end of the file**, outside of any `http {}` block:

```nginx
stream {
    upstream grokway_ssh {
        # Forward to the internal port where Grokway server is running (e.g., 2223)
        server 127.0.0.1:2223;
    }

    server {
        listen 2222; # Public facing SSH port
        proxy_pass grokway_ssh;
    }
}
```

After changing `nginx.conf`:
```bash
nginx -t
systemctl reload nginx
```

### 3. Run the Server

Since Nginx is now listening on port `2222` (public), you must run the Grokway server on a **different internal port** (e.g., `2223`) to avoid conflicts.

Running locally with Go:
```bash
go run cmd/server/main.go -ssh :2223
```

Running with Docker (update `docker-compose.yml`):
- Ensure the container exposes/maps port `2223` internally if needed, or simply let it run on default but map `2223:2222`? 
- Actually, better just pass the arg:
```bash
command: ["/app/grokway-server", "-ssh", ":2223"]
```
And update ports mapping:
```yaml
ports:
  - "127.0.0.1:2223:2223" # Only bind to localhost if Nginx is proxying
```
