Skip to content

Commit b1da679

Browse files
committed
feat(docs): add ssh sidecar image pipeline and docs
1 parent b9b7d45 commit b1da679

10 files changed

Lines changed: 132 additions & 12 deletions

File tree

.github/workflows/sshd-image.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: SSHD Sidecar Image
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [main]
7+
tags:
8+
- "v*"
9+
10+
jobs:
11+
build-and-push:
12+
runs-on: ubuntu-latest
13+
permissions:
14+
contents: read
15+
packages: write
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- uses: docker/setup-qemu-action@v3
20+
- uses: docker/setup-buildx-action@v3
21+
22+
- name: Login to GHCR
23+
uses: docker/login-action@v3
24+
with:
25+
registry: ghcr.io
26+
username: ${{ github.actor }}
27+
password: ${{ secrets.GITHUB_TOKEN }}
28+
29+
- name: Docker metadata
30+
id: meta
31+
uses: docker/metadata-action@v5
32+
with:
33+
images: ghcr.io/${{ github.repository_owner }}/okdev-sshd
34+
tags: |
35+
type=raw,value=edge,enable={{is_default_branch}}
36+
type=sha,prefix=edge-
37+
type=ref,event=tag
38+
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
39+
40+
- name: Build and push
41+
uses: docker/build-push-action@v6
42+
with:
43+
context: infra/sshd
44+
file: infra/sshd/Dockerfile
45+
platforms: linux/amd64,linux/arm64
46+
push: true
47+
tags: ${{ steps.meta.outputs.tags }}
48+
labels: ${{ steps.meta.outputs.labels }}

docs/command-reference.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
- `okdev use <session>`
2424
- `okdev connect [--shell /bin/bash] [--cmd "..."] [--no-tty]`
2525
- `okdev ssh [--setup-key] [--user root] [--cmd "..."]`
26+
- SSH target is configured by `spec.ssh.mode` (`dev-container` or `sidecar`).
27+
- `okdev` writes managed host aliases to `~/.ssh/config` as `okdev-<session>`.
2628
- `okdev ports`
2729
- `okdev sync [--mode up|down|bi] [--background] [--dry-run]`
2830
- `okdev prune [--ttl-hours 72] [--all-namespaces] [--all-users] [--include-pvc] [--dry-run]`

docs/okdev-design.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ spec:
126126
user: root
127127
remotePort: 22
128128
localPort: 2222
129+
mode: sidecar
130+
sidecarImage: ghcr.io/acmore/okdev-sshd:v0.1.0
129131
podTemplate:
130132
metadata:
131133
labels:
@@ -180,7 +182,7 @@ Notes:
180182
- Pod (or Deployment/StatefulSet later)
181183
- PVC(s) for workspace/cache
182184
- ConfigMap/Secret for metadata and credentials
183-
- Lease annotation/label for ownership and heartbeat
185+
- Labels/annotations for ownership and metadata
184186

185187
3. **Optional in-pod helper (small sidecar)**
186188
- Handles optimized sync endpoint and health checks
@@ -224,11 +226,11 @@ Ownership model:
224226
- scaffolds `.okdev.yaml` from template and detects language/runtime hints
225227
- supports `-c, --config` to generate a custom config filename/path
226228

227-
- `okdev up [--attach] [--name] [-c|--config]`
229+
- `okdev up [--no-attach] [--name] [-c|--config]`
228230
- create or resume session
229231
- wait for Pod Ready (watch-based readiness events)
230-
- optionally connect immediately
231-
- with `--attach`, auto-start configured port-forwarding and syncthing in background
232+
- by default, attach shell and auto-start configured sync/port-forward/ssh tunnel
233+
- with `--no-attach`, skip shell and background integrations
232234
- supports `--dry-run` to preview operations without applying
233235
- supports explicit `--session <name>` for multiple concurrent sessions per repo
234236

@@ -239,6 +241,8 @@ Ownership model:
239241
- `okdev ssh [--setup-key] [--cmd]`
240242
- SSH over auto-managed `kubectl port-forward`
241243
- optional in-pod public key bootstrap
244+
- writes managed host alias (`okdev-<session>`) to `~/.ssh/config`
245+
- supports `spec.ssh.mode=sidecar` to avoid requiring sshd in dev container
242246

243247
- `okdev sync [--mode=bi|up|down] [--background] [--dry-run]`
244248
- syncthing engine: continuous sync for single path mapping
@@ -285,9 +289,9 @@ Ownership model:
285289
- Sessions are labeled with `okdev.io/owner=<owner>`.
286290
- Mutating commands refuse non-owner sessions unless session is explicitly marked shareable.
287291

288-
Lease behavior:
289-
- Session heartbeat is updated in background for long-running commands (`connect`, `ssh`, `ports`, `sync`, and `up --attach`).
290-
- `okdev down` deletes the Lease object so exclusive sessions can be reacquired immediately.
292+
Heartbeat behavior:
293+
- Session heartbeat is updated in background for long-running commands (`connect`, `ssh`, `ports`, `sync`, and `up` default attach flow).
294+
- No Lease objects are required; implementation remains CRD-less and object-light.
291295

292296
## 10.1 Multi-Session Model (Multi-Project and Multi-Branch)
293297

docs/quickstart.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ For a named session:
6565
`okdev` auto-installs local Syncthing and auto-injects a pod sidecar when `sync.engine=syncthing`.
6666
Default sidecar image tag follows the running `okdev` binary version (`ghcr.io/<repo-owner>/okdev:<okdev-version>`). For dev builds, fallback is `ghcr.io/<repo-owner>/okdev:edge`. Update `spec.sync.syncthing.image` only if you publish to a different registry/repository.
6767
Use `spec.sync.exclude` for local ignore patterns and `spec.sync.remoteExclude` for remote-only ignore patterns.
68+
For SSH, default mode is `spec.ssh.mode=dev-container` (your dev image runs sshd). Set `spec.ssh.mode=sidecar` to use `ghcr.io/<repo-owner>/okdev-sshd:<okdev-version>` instead.
69+
`okdev ssh` and `okdev up` manage `~/.ssh/config` entries as `okdev-<session>`.
6870

6971
Preview-only mode (no cluster changes):
7072

docs/release.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@ git push origin v0.1.0
3333

3434
## Sidecar image tags
3535

36-
The sidecar image tag is aligned with the `okdev` release tag:
36+
Sidecar image tags are aligned with the `okdev` release tag:
3737

38-
- release `vX.Y.Z` publishes `ghcr.io/acmore/okdev:vX.Y.Z`
39-
- dev/main pushes publish `ghcr.io/acmore/okdev:edge`
38+
- release `vX.Y.Z` publishes:
39+
- `ghcr.io/acmore/okdev:vX.Y.Z` (syncthing sidecar)
40+
- `ghcr.io/acmore/okdev-sshd:vX.Y.Z` (SSH sidecar)
41+
- dev/main pushes publish:
42+
- `ghcr.io/acmore/okdev:edge`
43+
- `ghcr.io/acmore/okdev-sshd:edge`
4044

41-
`okdev` resolves default sidecar image from its own binary version, with `edge` fallback for dev builds.
45+
`okdev` resolves default sidecar images from its own binary version, with `edge` fallback for dev builds.
4246

4347
## Install from release
4448

docs/troubleshooting.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
## SSH connect issues
2828

29-
- Ensure an SSH server is running in the dev container.
29+
- Ensure an SSH server is available:
30+
- `spec.ssh.mode=dev-container`: dev container must run sshd.
31+
- `spec.ssh.mode=sidecar`: okdev injects `okdev-ssh` sidecar on port 22.
3032
- Use `okdev ssh --setup-key` once to install your public key in the pod.
3133
- If port `2222` is busy locally, pass `okdev ssh --local-port <port>`.
34+
- Check managed SSH alias in `~/.ssh/config` (`Host okdev-<session>`).

infra/sshd/Dockerfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM alpine:3.21
2+
3+
RUN apk add --no-cache openssh-server && \
4+
mkdir -p /run/sshd /root/.ssh && \
5+
chmod 700 /root/.ssh
6+
7+
COPY sshd_config /etc/ssh/sshd_config
8+
COPY entrypoint.sh /entrypoint.sh
9+
RUN chmod +x /entrypoint.sh
10+
11+
EXPOSE 22
12+
13+
ENTRYPOINT ["/entrypoint.sh"]

infra/sshd/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# okdev SSH Sidecar
2+
3+
This image provides an SSH daemon sidecar for `spec.ssh.mode=sidecar`.
4+
5+
Build locally:
6+
7+
```bash
8+
docker build -f infra/sshd/Dockerfile -t okdev-sshd:dev infra/sshd
9+
```
10+
11+
Run locally:
12+
13+
```bash
14+
docker run --rm -p 2222:22 okdev-sshd:dev
15+
```

infra/sshd/entrypoint.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/sh
2+
set -eu
3+
4+
mkdir -p /run/sshd /root/.ssh
5+
chmod 700 /root/.ssh
6+
touch /root/.ssh/authorized_keys
7+
chmod 600 /root/.ssh/authorized_keys
8+
9+
if [ ! -f /etc/ssh/ssh_host_ed25519_key ]; then
10+
ssh-keygen -A
11+
fi
12+
13+
exec /usr/sbin/sshd -D -e -f /etc/ssh/sshd_config

infra/sshd/sshd_config

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Port 22
2+
Protocol 2
3+
HostKey /etc/ssh/ssh_host_rsa_key
4+
HostKey /etc/ssh/ssh_host_ecdsa_key
5+
HostKey /etc/ssh/ssh_host_ed25519_key
6+
PermitRootLogin prohibit-password
7+
PasswordAuthentication no
8+
KbdInteractiveAuthentication no
9+
ChallengeResponseAuthentication no
10+
UsePAM no
11+
PubkeyAuthentication yes
12+
AuthorizedKeysFile .ssh/authorized_keys
13+
ClientAliveInterval 180
14+
ClientAliveCountMax 2
15+
PidFile /run/sshd/sshd.pid
16+
Subsystem sftp internal-sftp

0 commit comments

Comments
 (0)