aboutsummaryrefslogtreecommitdiffstats
path: root/skills/ship-setup/SKILL.md
blob: e3d08eecde06ea72a418733b1bccff6e930d1668 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
---
name: ship-setup
description: Set up ship for the first time or add a new VPS host. Saves host config to ~/.config/ship/config.json and installs server dependencies. Use when configuring ship for the first time, or adding/changing a host.
argument-hint: "[host-nickname]"
---

# ship-setup

Configure ship and prepare a VPS for deployments.

## Config File

All ship skills read from `~/.config/ship/config.json`. This skill creates or updates it.

Structure:
```json
{
  "default": "prod",
  "hosts": {
    "prod": {
      "host": "ubuntu@1.2.3.4",
      "domain": "example.com"
    },
    "staging": {
      "host": "ubuntu@5.6.7.8",
      "domain": "staging.example.com"
    }
  }
}
```

## Steps

### 1. Read existing config

Check if `~/.config/ship/config.json` exists:

```bash
cat ~/.config/ship/config.json 2>/dev/null
```

If it exists, show the user the current hosts so they know what's already configured.

### 2. Get host details

If no nickname was provided as an argument, ask the user:
- **Nickname** — a short name for this host (e.g. `prod`, `staging`, `vps`)
- **SSH connection string** — e.g. `ubuntu@1.2.3.4` or an SSH config alias like `alaskav6`
- **Base domain** — the domain pointing to this server (e.g. `example.com`)

If this is the first host, ask if it should be the default. If hosts already exist, ask if this should replace the current default.

### 3. Test SSH connection

Verify the connection works before saving anything:

```bash
ssh -o ConnectTimeout=5 <host> "echo ok"
```

If it fails, tell the user and stop. Don't save config for an unreachable host.

### 4. Save config

Write or update `~/.config/ship/config.json` with the new host. Merge with existing hosts — never overwrite the whole file. Use Python to safely read/write JSON:

```bash
python3 -c "
import json, os
path = os.path.expanduser('~/.config/ship/config.json')
os.makedirs(os.path.dirname(path), exist_ok=True)
cfg = json.load(open(path)) if os.path.exists(path) else {'default': None, 'hosts': {}}
cfg['hosts']['<nickname>'] = {'host': '<ssh-host>', 'domain': '<domain>'}
if not cfg['default']:
    cfg['default'] = '<nickname>'
json.dump(cfg, open(path, 'w'), indent=2)
print('saved')
"
```

### 5. Install server dependencies

SSH in and ensure the required directories and software exist. This is idempotent — safe to run multiple times.

**Install Caddy** (if not present):
```bash
ssh <host> "which caddy || (sudo apt-get install -y debian-keyring debian-archive-keyring apt-transport-https curl && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg && curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list && sudo apt-get update && sudo apt-get install -y caddy)"
```

**Create directory structure:**
```bash
ssh <host> "sudo mkdir -p /etc/ship/env /etc/ship/ports /etc/caddy/sites-enabled /var/www && sudo chmod 755 /etc/ship"
```

**Configure main Caddyfile** (only if not already set up):
```bash
ssh <host> "sudo test -f /etc/caddy/Caddyfile && echo exists || echo '{
}

import /etc/caddy/sites-enabled/*' | sudo tee /etc/caddy/Caddyfile"
```

**Enable and start Caddy:**
```bash
ssh <host> "sudo systemctl enable caddy && sudo systemctl start caddy"
```

### 6. Confirm

Tell the user:
- Host nickname and SSH target saved
- Whether it's the default host
- That the server is ready for deployments
- How to add another host: `/ship-setup <nickname>`
- How to deploy: `/ship-deploy`

## Notes

- Never overwrite the entire config file — always merge
- If a nickname already exists in config, confirm before overwriting it
- The SSH host can be an alias from `~/.ssh/config` — no need to require raw IP
- Default host is used by all other ship skills when no host is specified