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
6 changes: 5 additions & 1 deletion apps/docs/docs/development/dev-stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ deploy/scripts/create-agent-dev-container.sh
```

The helper reads `.dev/dev.env`, creates one long-lived systemd Ubuntu
container, and runs the normal CT-Ops agent install script inside it.
container, publishes the container SSH service on a random loopback host port,
and runs the normal CT-Ops agent install script inside it. The selected SSH port
is printed after creation and can also be checked with
`docker port <container> 22/tcp`. The helper creates an SSH login user named
`ssh-user` with password `password` by default.

Switch back to loopback-only mode with:

Expand Down
4 changes: 3 additions & 1 deletion deploy/docker/agent-dev-container/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ RUN apt-get update \
&& apt-get install -y --no-install-recommends \
ca-certificates \
curl \
openssh-server \
sudo \
systemd \
systemd-sysv \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& useradd --system --create-home --shell /usr/sbin/nologin ctops-agent
&& useradd --system --create-home --shell /usr/sbin/nologin ctops-agent \
&& systemctl enable ssh.service

STOPSIGNAL SIGRTMIN+3

Expand Down
50 changes: 50 additions & 0 deletions deploy/scripts/create-agent-dev-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ INGEST_ADDRESS="${CT_OPS_AGENT_INGEST_ADDRESS:-ingest-dev:9443}"
CONTAINER_NAME="${CT_OPS_AGENT_CONTAINER_NAME:-ctops-agent-$(date -u +%Y%m%d%H%M%S)-${RANDOM}}"
ENROLMENT_TOKEN="${CT_OPS_ENROLMENT_TOKEN:-}"
DOCKER_NETWORK="${CT_OPS_AGENT_DOCKER_NETWORK:-}"
SSH_BIND_ADDRESS="${CT_OPS_AGENT_SSH_BIND_ADDRESS:-127.0.0.1}"
SSH_USERNAME="${CT_OPS_AGENT_SSH_USERNAME:-ssh-user}"
SSH_PASSWORD="${CT_OPS_AGENT_SSH_PASSWORD:-password}"
SKIP_VERIFY="true"
INSTALL_AGENT="true"

Expand All @@ -33,6 +36,12 @@ Options:
Default: ${IMAGE_TAG}
--network NAME Docker network containing the dev stack.
Default: COMPOSE_PROJECT_NAME_default from ${DEV_ENV}
--ssh-bind-address IP Host interface for the random SSH port publish.
Default: ${SSH_BIND_ADDRESS}
--ssh-user USER SSH login user to create in the container.
Default: ${SSH_USERNAME}
--ssh-password PASS Password for the SSH login user.
Default: ${SSH_PASSWORD}
--no-skip-verify Do not request TLS skip verification in the install script.
--no-install Create the container but do not run the agent installer.
-h, --help Show this help.
Expand Down Expand Up @@ -125,6 +134,23 @@ wait_for_systemd() {
die "systemd did not become ready in container ${name}"
}

configure_ssh_user() {
local name="$1"
local username="$2"
local password="$3"

docker exec \
-e CT_OPS_AGENT_SSH_USERNAME="$username" \
-e CT_OPS_AGENT_SSH_PASSWORD="$password" \
"$name" \
sh -euc '
if ! id "$CT_OPS_AGENT_SSH_USERNAME" >/dev/null 2>&1; then
useradd --create-home --shell /bin/bash "$CT_OPS_AGENT_SSH_USERNAME"
fi
printf "%s:%s\n" "$CT_OPS_AGENT_SSH_USERNAME" "$CT_OPS_AGENT_SSH_PASSWORD" | chpasswd
'
}

load_dev_env_defaults

while [ "$#" -gt 0 ]; do
Expand Down Expand Up @@ -159,6 +185,21 @@ while [ "$#" -gt 0 ]; do
DOCKER_NETWORK="$2"
shift 2
;;
--ssh-bind-address)
[ "$#" -ge 2 ] || die "--ssh-bind-address requires a value"
SSH_BIND_ADDRESS="$2"
shift 2
;;
--ssh-user)
[ "$#" -ge 2 ] || die "--ssh-user requires a value"
SSH_USERNAME="$2"
shift 2
;;
--ssh-password)
[ "$#" -ge 2 ] || die "--ssh-password requires a value"
SSH_PASSWORD="$2"
shift 2
;;
--no-skip-verify)
SKIP_VERIFY="false"
shift
Expand Down Expand Up @@ -204,6 +245,7 @@ docker_run_args=(
--cgroupns=host
--restart unless-stopped
--add-host host.docker.internal:host-gateway
--publish "${SSH_BIND_ADDRESS}::22"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Normalize IPv6 SSH bind addresses before publish

Using --ssh-bind-address with an IPv6 literal (for example ::1) currently produces --publish ::1::22, which Docker parses incorrectly because IPv6 host IPs must be bracketed in publish mappings (e.g. [::1]:...). This makes container startup fail for IPv6 bind-address use cases even though the flag is documented as accepting an IP address. Consider normalizing IPv6 values (or requiring bracketed input) before composing the --publish argument.

Useful? React with 👍 / 👎.

--tmpfs /run
--tmpfs /run/lock
--volume /sys/fs/cgroup:/sys/fs/cgroup:rw
Expand All @@ -215,6 +257,8 @@ docker_run_args+=("$IMAGE_TAG")
docker run "${docker_run_args[@]}" >/dev/null

wait_for_systemd "$CONTAINER_NAME"
configure_ssh_user "$CONTAINER_NAME" "$SSH_USERNAME" "$SSH_PASSWORD"
ssh_endpoint="$(docker port "$CONTAINER_NAME" 22/tcp 2>/dev/null | head -n1 || true)"

if [ "$INSTALL_AGENT" = "true" ]; then
install_url="${APP_URL}/api/agent/install?ingest=$(urlencode "$INGEST_ADDRESS")"
Expand All @@ -233,5 +277,11 @@ fi

echo ""
echo "Container: ${CONTAINER_NAME}"
if [ -n "$ssh_endpoint" ]; then
echo "SSHD: ${ssh_endpoint} -> 22/tcp"
echo "SSH Login: ssh -p ${ssh_endpoint##*:} ${SSH_USERNAME}@${ssh_endpoint%:*}"
else
echo "SSHD: docker port ${CONTAINER_NAME} 22/tcp"
fi
echo "Status: docker exec -it ${CONTAINER_NAME} systemctl status ct-ops-agent"
echo "Logs: docker exec -it ${CONTAINER_NAME} journalctl -u ct-ops-agent -f"
34 changes: 34 additions & 0 deletions deploy/scripts/test-create-agent-dev-container.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ case "${1:-}" in
run)
exit 0
;;
port)
echo "127.0.0.1:32768"
exit 0
;;
exec)
if printf '%s\n' "$*" | grep -q 'test -d /run/systemd/system'; then
exit 0
Expand Down Expand Up @@ -109,11 +113,31 @@ EOF
cat "$log" >&2
exit 1
fi
if ! grep -q -- "--publish 127.0.0.1::22" "$log"; then
echo "expected sshd port publish on a random loopback host port" >&2
cat "$log" >&2
exit 1
fi
if ! grep -Fq -- "CT_OPS_ENROLMENT_TOKEN=dev_env_token" "$log"; then
echo "expected enrolment token from dev env" >&2
cat "$log" >&2
exit 1
fi
if ! grep -Fq -- "CT_OPS_AGENT_SSH_USERNAME=ssh-user" "$log"; then
echo "expected default ssh username" >&2
cat "$log" >&2
exit 1
fi
if ! grep -Fq -- "CT_OPS_AGENT_SSH_PASSWORD=password" "$log"; then
echo "expected default ssh password" >&2
cat "$log" >&2
exit 1
fi
if ! grep -Fq -- "useradd --create-home --shell /bin/bash" "$log"; then
echo "expected ssh user creation" >&2
cat "$log" >&2
exit 1
fi
if ! grep -Fq -- "CT_OPS_AGENT_INSTALL_URL=http://dev-env-host:3000/api/agent/install\\?ingest=dev-env-host%3A9443\\&skip_verify=true" "$log"; then
echo "expected install URL with encoded ingest address and skip_verify" >&2
cat "$log" >&2
Expand All @@ -129,6 +153,16 @@ EOF
echo "$output" >&2
exit 1
fi
if [[ "$output" != *"SSHD: 127.0.0.1:32768 -> 22/tcp"* ]]; then
echo "expected sshd port mapping hint" >&2
echo "$output" >&2
exit 1
fi
if [[ "$output" != *"SSH Login: ssh -p 32768 ssh-user@127.0.0.1"* ]]; then
echo "expected ssh login hint" >&2
echo "$output" >&2
exit 1
fi

echo "create-agent-dev-container.sh command assembly test passed"
}
Expand Down
Loading