Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,15 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

### Added

- `easy proxy verify` — checks the proxy container is actually running and
surfaces the startup error if it crashed. `easy proxy create` now runs this
check automatically, so it no longer reports success when nginx failed to
start.

## [2.1.0] — 2026-05-18

### Added
Expand Down
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ easy proxy status # → container ID se running
| `easy proxy status` | Container ID se running, vuoto se fermo |
| `easy proxy id` | Container ID (`docker ps` per nome `easy-proxy`, anche se fermo) |
| `easy proxy doctor` | Diagnosi read-only: vhost non-standard, `nginx -t`, reti del proxy |
| `easy proxy verify` | Verifica che il proxy sia davvero up; `create` la esegue da solo |
| `easy proxy attach\|detach <container>` | Collega/scollega un container alla rete edge `EASY_PROXY_NETWORK` |
| `easy proxy networks [prune]` | Mostra le reti del proxy; `prune` scollega quelle non-edge |
| `easy proxy start/stop/restart` | Ciclo container |
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ Run `easy proxy help` for the full list.
| `easy proxy status` | Container id if running, empty if stopped |
| `easy proxy id` | Container id (running or stopped) |
| `easy proxy doctor` | Read-only diagnostic: non-standard vhosts, `nginx -t`, proxy networks |
| `easy proxy verify` | Check the proxy is actually running; `create` runs it automatically |
| `easy proxy attach` / `detach <container>` | Connect/disconnect a site container to the edge network |
| `easy proxy networks [prune]` | Show the proxy's networks; `prune` disconnects non-edge ones |
| `easy proxy start` / `stop` / `restart` | Container lifecycle |
Expand Down
29 changes: 27 additions & 2 deletions commands/proxy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function __easy_command_proxy_help {
echo " easy proxy id"
echo " easy proxy status"
echo " easy proxy doctor"
echo " easy proxy verify"
echo " easy proxy attach <container>"
echo " easy proxy detach <container>"
echo " easy proxy networks [prune]"
Expand Down Expand Up @@ -230,6 +231,10 @@ chmod 600 /etc/letsencrypt/ionos.ini"
__easy_command_proxy_doctor
return $?
fi
if [[ "verify" == "$2" ]]; then
__easy_command_proxy_verify
return $?
fi
if [[ "attach" == "$2" ]]; then
__easy_command_proxy_attach "$3"
return $?
Expand All @@ -251,6 +256,23 @@ chmod 600 /etc/letsencrypt/ionos.ini"
fi
}

# Check the proxy container is actually running; on failure surface the reason.
function __easy_command_proxy_verify {
if [[ -n "$(easy proxy status)" ]]; then
echo "easy proxy: running"
return 0
fi
echo "easy proxy: NOT running"
if [[ -n "$(easy proxy id)" ]]; then
echo "the container exited — last log lines:"
docker logs --tail 15 "${EASY_PROXY_NAME}" 2>&1 | sed 's/^/ /'
echo "fix the cause, then 'easy proxy destroy' and 'easy proxy create' again."
else
echo "no ${EASY_PROXY_NAME} container — run 'easy proxy create'."
fi
return 1
}

function __easy_command_proxy_create {
if [[ -n "$(easy proxy id)" ]]; then
echo "There is already an easy proxy instance named ${EASY_PROXY_NAME}"
Expand Down Expand Up @@ -278,8 +300,11 @@ function __easy_command_proxy_create {
-v "${EASY_DIR}/easyhome:/usr/local/share/easy" \
-p 80:80 \
-p 443:443 \
-t ethiclab/nginx-easy
return $?
-t ethiclab/nginx-easy || return $?
# `docker run` only starts the container — nginx can still crash on a bad
# config. Give it a moment, then verify the proxy is actually serving.
sleep "${EASY_VERIFY_DELAY:-2}"
__easy_command_proxy_verify
}

# Read-only pre-flight diagnostic: static vhost analysis (host-side) plus,
Expand Down
6 changes: 4 additions & 2 deletions test/network.bats
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ setup() { easy_setup; }
@test "easy proxy create joins EASY_PROXY_NETWORK and auto-creates it" {
export EASY_PROXY_NETWORK=ethicnet
export DOCKER_LOG="$BATS_TEST_TMPDIR/docker.log"
mock_docker_record
mock_docker_lifecycle
export DOCKER_PROXY_HEALTHY=1
run easy proxy create
[ "$status" -eq 0 ]
grep -q "network create ethicnet" "$DOCKER_LOG"
Expand All @@ -25,7 +26,8 @@ setup() { easy_setup; }

@test "easy proxy create stays on the default network when EASY_PROXY_NETWORK is unset" {
export DOCKER_LOG="$BATS_TEST_TMPDIR/docker.log"
mock_docker_record
mock_docker_lifecycle
export DOCKER_PROXY_HEALTHY=1
run easy proxy create
[ "$status" -eq 0 ]
! grep -q -- "--network" "$DOCKER_LOG"
Expand Down
3 changes: 2 additions & 1 deletion test/proxy.bats
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ setup() { easy_setup; }
}

@test "easy proxy create writes no state file into the install dir (#5)" {
mock_docker_stopped
mock_docker_lifecycle
export DOCKER_PROXY_HEALTHY=1
chmod -w "$EASY_CLI_DIR"
run easy proxy create
chmod +w "$EASY_CLI_DIR"
Expand Down
24 changes: 24 additions & 0 deletions test/test_helper.bash
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,30 @@ easy_setup() {

# Deterministic: never inherit real credentials/config from the host shell.
unset IONOS_API_KEY IONOS_API_SECRET EASY_LETSENCRYPT_EMAIL EASY_LETSENCRYPT_DOMAIN EASY_PROXY_NETWORK
# Skip the post-create verify wait — the mocks settle instantly.
export EASY_VERIFY_DELAY=0
}

# Stateful `docker` mock for `create` + `verify`. `run` marks the container
# created; `ps -a` (id) then reports it; `ps` (running) reports it only when
# DOCKER_PROXY_HEALTHY is set — leave it unset to simulate a startup crash.
mock_docker_lifecycle() {
export DOCKER_STATE="$BATS_TEST_TMPDIR/docker-state"
rm -f "$DOCKER_STATE"
cat > "$MOCK_BIN/docker" <<'MOCK'
#!/usr/bin/env bash
echo "$*" >> "${DOCKER_LOG:-/dev/null}"
case "$1 $2" in
"run "*) echo created > "$DOCKER_STATE"; echo "deadbeefcafe1234" ;;
"ps -a"*) [ -f "$DOCKER_STATE" ] && echo "deadbeefcafe1234" ;;
"ps "*) { [ -f "$DOCKER_STATE" ] && [ -n "$DOCKER_PROXY_HEALTHY" ]; } && echo "deadbeefcafe1234" ;;
"logs "*) echo 'nginx: [emerg] host not found in upstream "x"' ;;
"network inspect"*) exit 1 ;;
"stop "*|"rm "*) rm -f "$DOCKER_STATE" ;;
*) exit 0 ;;
esac
MOCK
chmod +x "$MOCK_BIN/docker"
}

# Mock `docker` so `docker ps` reports a fake running easy-proxy container.
Expand Down
49 changes: 49 additions & 0 deletions test/verify.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/env bats
# Tests for `easy proxy verify` and the auto-verify wired into `easy proxy create`.

load test_helper

setup() { easy_setup; }

@test "easy proxy help lists verify" {
run easy proxy help
[ "$status" -eq 0 ]
[[ "$output" == *"easy proxy verify"* ]]
}

@test "easy proxy verify exits 0 when the proxy is running" {
mock_docker_running
run easy proxy verify
[ "$status" -eq 0 ]
[[ "$output" == *"running"* ]]
}

@test "easy proxy verify fails when there is no proxy container" {
mock_docker_stopped
run easy proxy verify
[ "$status" -ne 0 ]
[[ "$output" == *"NOT running"* ]]
}

@test "easy proxy verify surfaces the startup error when the container has exited" {
mock_docker_lifecycle # DOCKER_PROXY_HEALTHY unset → container not running
touch "$DOCKER_STATE" # ...but a container exists
run easy proxy verify
[ "$status" -ne 0 ]
[[ "$output" == *"emerg"* ]]
}

@test "easy proxy create auto-verifies a healthy proxy" {
mock_docker_lifecycle
export DOCKER_PROXY_HEALTHY=1
run easy proxy create
[ "$status" -eq 0 ]
[[ "$output" == *"running"* ]]
}

@test "easy proxy create fails when the proxy crashes on startup" {
mock_docker_lifecycle # no DOCKER_PROXY_HEALTHY → nginx 'crashes'
run easy proxy create
[ "$status" -ne 0 ]
[[ "$output" == *"emerg"* ]]
}
Loading