chore: archive optional stacks, ship.sh, buildinfo

This commit is contained in:
Leopere 2026-04-01 11:42:07 -04:00
parent 8024cddc7c
commit 650482c189
Signed by: colin
SSH Key Fingerprint: SHA256:nRPCQTeMFLdGytxRQmPVK9VXY3/ePKQ5lGRyJhT5DY8
19 changed files with 166 additions and 27 deletions

View File

@ -1,5 +1,5 @@
# Copy to .env, set values, and never commit .env.
# Used by docker-compose-macmini.yml and docker-compose-logos.yml for tunnel HTTP Basic auth.
# Used by archive/docker-compose-macmini.yml and archive/docker-compose-logos.yml for tunnel HTTP Basic auth.
TUNNEL_AUTH_USER=
TUNNEL_AUTH_PASS=

View File

@ -134,10 +134,12 @@ Set `TUNNEL_AUTH_USER` / `TUNNEL_AUTH_PASS` via an env file; never commit passwo
For WebDAV stacks (macmini, logos) and any client using HTTP Basic Auth at the tunnel: copy `.env.example` to `.env`, set `TUNNEL_AUTH_USER` and `TUNNEL_AUTH_PASS`, and **never commit `.env`**. Compose files reference `${TUNNEL_AUTH_USER}` and `${TUNNEL_AUTH_PASS}`; Docker Compose reads `.env` from the project directory automatically.
#### WebDAV stacks (macmini / logos)
#### WebDAV stacks (macmini / logos) — in `archive/`
- **Macmini:** `docker compose -f docker-compose-macmini.yml up -d --build` — ensure `.env` has tunnel auth set.
- **Logos:** `docker compose -f docker-compose-logos.yml -p logos up -d --build` — same `.env` or separate; images/SVG-only uploads.
- **Macmini:** from repo root: `docker compose -f archive/docker-compose-macmini.yml up -d --build` — ensure `.env` has tunnel auth set.
- **Logos:** `docker compose -f archive/docker-compose-logos.yml -p logos up -d --build` — same `.env` or separate; images/SVG-only uploads.
See `archive/README.md` for other archived files (Woodpecker CI, reference Traefik YAML, old root binaries).
## Generated Traefik Config
@ -164,7 +166,7 @@ http:
## Building
```bash
# Build both binaries locally (commit and push these for remote deployment)
# Build both binaries locally
go build -o tunnel-server ./cmd/server/
go build -o tunnel-client ./cmd/client/
@ -173,9 +175,11 @@ docker compose build # server image
docker build --target client -t tunnel-client . # client image
```
Release to GitHub + GHCR (multi-arch): `./ship.sh "your message"` (requires `gh` with `write:packages` and git remote `github`).
## Binaries and systemd (bare metal)
The repo ships compiled `tunnel-server` and `tunnel-client` for remote hosts that run without Docker. Use the included systemd units under `systemd/`.
Build `tunnel-server` / `tunnel-client` with `go build` (or use `./ship.sh`, which writes `dist/`). Use the included systemd units under `systemd/`.
**Keys:** Do not reuse the hosts SSH keys or share one key between hosts or tunnels. Generate a dedicated ed25519 key per tunnel (or per host). Add that keys **public** half to the **tunnel** users `authorized_keys` on **ingress.nixc.us** (the reverse tunnel server).
@ -207,10 +211,10 @@ sudo systemctl daemon-reload && sudo systemctl enable --now tunnel-client
### Client on a remote host (clone or copy)
1. Install the binary (from repo clone or raw URL above; repo has `client`/`server`):
1. Install the binary (from repo clone, `go build`, `dist/tunnel-client` after `./ship.sh`, or raw URL):
```bash
sudo cp client /usr/local/bin/tunnel-client && sudo chmod +x /usr/local/bin/tunnel-client
sudo cp dist/tunnel-client /usr/local/bin/tunnel-client && sudo chmod +x /usr/local/bin/tunnel-client
```
2. Copy the systemd unit and create env file:

14
archive/README.md Normal file
View File

@ -0,0 +1,14 @@
# Archive (review / optional stacks)
Items here are **not** required for the core tunnel server and client (`cmd/server`, `cmd/client`).
| Item | Purpose |
|------|---------|
| `cmd-webdav/` | WebDAV app source (logos / macmini stacks) |
| `webdav/` | Dockerfile + entrypoint for that app |
| `docker-compose-macmini.yml` | Mac mini WebDAV + tunnel (run from repo root: `-f archive/docker-compose-macmini.yml`) |
| `docker-compose-logos.yml` | Logos WebDAV + tunnel |
| `woodpecker.yml` | CI pipeline (was `.woodpecker.yml` at repo root) |
| `traefik-reference.yml` | Sample Traefik stack |
| `test-index.html` | Used by `docker-compose.test.yml` in repo root |
| `client`, `server` | Old committed macOS binaries (prefer `go build` or Docker images) |

View File

@ -2,7 +2,7 @@
# Server (ingress) must be configured for this domain and key.
#
# Auth: set TUNNEL_AUTH_USER and TUNNEL_AUTH_PASS in .env (see .env.example); never commit .env.
# Deploy (separate from macmini): docker compose -f docker-compose-logos.yml -p logos up -d --build
# Deploy (separate from macmini): docker compose -f archive/docker-compose-logos.yml -p logos up -d --build
#
# Connect in Finder: Go → Connect to Server → https://logos.nixc.us
# Only image and SVG files can be uploaded (company logos).
@ -10,8 +10,8 @@
services:
webdav:
build:
context: .
dockerfile: webdav/Dockerfile
context: ..
dockerfile: archive/webdav/Dockerfile
restart: always
environment:
WEBDAV_IMAGES_ONLY: "1"

View File

@ -12,8 +12,8 @@
services:
webdav:
build:
context: .
dockerfile: webdav/Dockerfile
context: ..
dockerfile: archive/webdav/Dockerfile
restart: always
volumes:
- ${HOME}/dev/piconfigurator/bin:/data

View File

@ -1,14 +1,14 @@
# Build from repo root so go.mod and cmd/webdav are available (build context: .).
# Build context must be the repository root (see archive/docker-compose-*.yml).
FROM golang:1.24-alpine AS build
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o /webdav ./cmd/webdav
RUN go build -o /webdav ./archive/cmd-webdav
FROM alpine:3.20
RUN apk add --no-cache ca-certificates
COPY webdav/entrypoint.sh /entrypoint.sh
COPY archive/webdav/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
COPY --from=build /webdav /webdav
EXPOSE 80

View File

@ -6,7 +6,7 @@ services:
image: nginx:alpine
restart: always
volumes:
- ./test-index.html:/usr/share/nginx/html/index.html:ro
- ./archive/test-index.html:/usr/share/nginx/html/index.html:ro
expose:
- "80"

8
go.mod
View File

@ -4,9 +4,9 @@ go 1.24.0
toolchain go1.24.13
require golang.org/x/crypto v0.48.0
require (
golang.org/x/net v0.50.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/crypto v0.48.0
golang.org/x/net v0.50.0
)
require golang.org/x/sys v0.41.0 // indirect

7
go.sum
View File

@ -1,13 +1,8 @@
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=

View File

@ -0,0 +1,5 @@
// Package buildinfo holds values set at link time (-ldflags -X).
package buildinfo
// Commit is the git SHA baked in by Docker / ship.sh.
var Commit = "unknown"

121
ship.sh Executable file
View File

@ -0,0 +1,121 @@
#!/usr/bin/env bash
# Reliable release: commit → local binaries → multi-arch images → GHCR → git push.
# Only input: commit message. Edit CONSTANTS to change registry/platforms.
#
# Usage: ./ship.sh "your message"
set -euo pipefail
if [[ $# -lt 1 ]] || [[ -z "${1// }" ]]; then
echo "usage: $0 <commit message>" >&2
exit 1
fi
COMMIT_MSG="$*"
ROOT="$(cd "$(dirname "$0")" && pwd)"
cd "$ROOT"
# --- CONSTANTS ---
GITHUB_OWNER="Leopere"
GITHUB_REPO="better-argo-tunnels"
REGISTRY_BASE="ghcr.io/leopere/better-argo-tunnels"
TAG_SERVER="production"
TAG_CLIENT="client-production"
PLATFORMS="linux/amd64,linux/arm64,linux/arm/v7"
GIT_REMOTE="github"
# --- end ---
for cmd in gh docker git go; do
command -v "$cmd" >/dev/null 2>&1 || {
echo "error: need $cmd in PATH" >&2
exit 1
}
done
BRANCH="$(git branch --show-current)"
if [[ -z "$BRANCH" ]]; then
echo "error: detached HEAD" >&2
exit 1
fi
echo "==> git add -A"
git add -A
if git diff --cached --quiet; then
echo "error: nothing to commit" >&2
exit 1
fi
echo "==> git commit"
git commit -m "$COMMIT_MSG"
GIT_COMMIT="$(git rev-parse HEAD)"
BA=(--build-arg "GIT_COMMIT=$GIT_COMMIT")
LDFLAGS="-s -w -X github.com/nixc/reverse-ssh-traefik/internal/buildinfo.Commit=${GIT_COMMIT}"
echo "==> go build → dist/"
mkdir -p dist
CGO_ENABLED=0 go build -ldflags="$LDFLAGS" -o dist/tunnel-server ./cmd/server/
CGO_ENABLED=0 go build -ldflags="$LDFLAGS" -o dist/tunnel-client ./cmd/client/
pick_builder() {
if docker buildx inspect orbstack >/dev/null 2>&1; then
echo "orbstack"
else
echo "default"
fi
}
platform_slug() {
local p="${1// /}"
p="${p#linux/}"
echo "${p//\//-}"
}
push_multi() {
local target="$1"
local final_tag="$2"
local builder="$3"
local base="${final_tag%:*}"
local name="${final_tag##*:}"
local arch_refs=()
IFS=',' read -ra plats <<< "$PLATFORMS"
for p in "${plats[@]}"; do
p="${p// /}"
[[ -z "$p" ]] && continue
local slug
slug="$(platform_slug "$p")"
local arch_tag="${base}:${name}-${slug}"
echo "==> docker buildx $target $p$arch_tag"
docker buildx build \
"${BA[@]}" \
--builder "$builder" \
--platform "$p" \
--target "$target" \
-t "$arch_tag" \
--push \
"$ROOT"
arch_refs+=("$arch_tag")
done
docker buildx imagetools create -t "$final_tag" "${arch_refs[@]}"
}
BUILDER="$(pick_builder)"
SERVER_TAG="${REGISTRY_BASE}:${TAG_SERVER}"
CLIENT_TAG="${REGISTRY_BASE}:${TAG_CLIENT}"
echo "==> ghcr.io login (needs gh token with write:packages)"
echo "$(gh auth token)" | docker login ghcr.io -u "$GITHUB_OWNER" --password-stdin
push_multi server "$SERVER_TAG" "$BUILDER"
push_multi client "$CLIENT_TAG" "$BUILDER"
if ! git remote get-url "$GIT_REMOTE" >/dev/null 2>&1; then
echo "error: git remote '$GIT_REMOTE' missing" >&2
exit 1
fi
echo "==> git push $GIT_REMOTE $BRANCH"
git push "$GIT_REMOTE" "$BRANCH"
echo "==> ok commit=$GIT_COMMIT"
echo " $SERVER_TAG $CLIENT_TAG"