@@ -0,0 +1,26 @@
|
||||
FROM debian:trixie-slim
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ca-certificates \
|
||||
libdrm2 \
|
||||
libegl1 \
|
||||
libgbm1 \
|
||||
libgl1 \
|
||||
libgles2 \
|
||||
libglvnd0 \
|
||||
libstdc++6 \
|
||||
libudev1 \
|
||||
libx11-6 \
|
||||
libxcb1 \
|
||||
sqlite3 \
|
||||
tini \
|
||||
util-linux \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY usr/ /usr/
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["/usr/bin/vamp-zero", "--config", "/etc/product-vamp/vamp.json"]
|
||||
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
bundle_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
zero_dir="$bundle_dir/zero"
|
||||
image_tar="$zero_dir/product-vamp-zero-linux-arm64.docker.tar"
|
||||
config_dir=/etc/product-vamp
|
||||
state_dir=/var/lib/product-vamp
|
||||
run_dir=/run/product-vamp
|
||||
share_dir=/usr/share/product-vamp
|
||||
required_packages=(
|
||||
docker.io
|
||||
docker-cli
|
||||
network-manager
|
||||
sqlite3
|
||||
ca-certificates
|
||||
python3
|
||||
)
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "install-zero.sh must be run as root" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$image_tar" ]; then
|
||||
echo "missing Docker archive: $image_tar" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
missing_packages=()
|
||||
for package in "${required_packages[@]}"; do
|
||||
if ! dpkg-query -W -f='${Status}' "$package" 2>/dev/null | grep -qx 'install ok installed'; then
|
||||
missing_packages+=("$package")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#missing_packages[@]}" -eq 0 ]; then
|
||||
echo "Required OS packages already installed; skipping apt."
|
||||
else
|
||||
echo "Installing missing OS packages: ${missing_packages[*]}"
|
||||
if ! apt-get update -o APT::Update::Error-Mode=any; then
|
||||
echo "Failed to refresh apt package indexes." >&2
|
||||
echo "Connect the Zero to upstream internet, then rerun sudo zero/install-zero.sh." >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! apt-get install -y --no-install-recommends "${missing_packages[@]}"; then
|
||||
echo "Failed to install required OS packages: ${missing_packages[*]}" >&2
|
||||
echo "Connect the Zero to upstream internet, then rerun sudo zero/install-zero.sh." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
systemctl enable --now docker NetworkManager
|
||||
|
||||
install -d -m 0755 "$config_dir" "$state_dir" "$run_dir" "$share_dir"
|
||||
cp -R "$zero_dir/share/product-vamp/." "$share_dir/"
|
||||
|
||||
if [ ! -f "$config_dir/vamp.json" ]; then
|
||||
cp "$zero_dir/config/vamp.example.json" "$config_dir/vamp.json"
|
||||
fi
|
||||
|
||||
docker load -i "$image_tar"
|
||||
|
||||
install -m 0755 "$zero_dir/start-ap.sh" /usr/local/bin/product-vamp-start-ap
|
||||
install -m 0755 "$zero_dir/start-zero.sh" /usr/local/bin/product-vamp-start-zero
|
||||
install -m 0644 "$zero_dir/systemd/product-vamp-ap.service" /etc/systemd/system/product-vamp-ap.service
|
||||
install -m 0644 "$zero_dir/systemd/product-vamp-zero.service" /etc/systemd/system/product-vamp-zero.service
|
||||
|
||||
systemctl daemon-reload
|
||||
systemctl disable --now getty@tty1.service >/dev/null 2>&1 || true
|
||||
systemctl enable --now getty@tty2.service >/dev/null 2>&1 || true
|
||||
systemctl enable --now product-vamp-ap.service
|
||||
systemctl enable product-vamp-zero.service
|
||||
systemctl restart product-vamp-zero.service
|
||||
|
||||
echo "Product Vamp Zero installed. Control AP defaults to SSID 'Vamp Control' at http://192.168.42.1:8080."
|
||||
@@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=Product Vamp Wi-Fi control access point
|
||||
After=NetworkManager.service
|
||||
Requires=NetworkManager.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=/usr/local/bin/product-vamp-start-ap
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Product Vamp Zero display and control service
|
||||
After=docker.service product-vamp-ap.service getty@tty1.service
|
||||
Requires=docker.service product-vamp-ap.service
|
||||
Conflicts=getty@tty1.service
|
||||
|
||||
[Service]
|
||||
Restart=always
|
||||
RestartSec=3
|
||||
TTYPath=/dev/tty1
|
||||
TTYReset=yes
|
||||
TTYVHangup=yes
|
||||
TTYVTDisallocate=yes
|
||||
StandardInput=tty-force
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
ExecStartPre=/usr/bin/install -d -m 0755 /run/product-vamp
|
||||
ExecStart=/usr/local/bin/product-vamp-start-zero
|
||||
ExecStop=/bin/sh -c '/usr/bin/docker stop product-vamp-zero >/dev/null 2>&1 || true'
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
config=${PRODUCT_VAMP_CONFIG:-/etc/product-vamp/vamp.json}
|
||||
ssid=${PRODUCT_VAMP_AP_SSID:-Vamp Control}
|
||||
passphrase=${PRODUCT_VAMP_AP_PASSPHRASE:-vamp-control}
|
||||
interface=${PRODUCT_VAMP_AP_INTERFACE:-wlan0}
|
||||
cidr=${PRODUCT_VAMP_ZERO_CIDR:-192.168.42.1/24}
|
||||
connection=${PRODUCT_VAMP_AP_CONNECTION:-product-vamp-control}
|
||||
|
||||
configure_connection() {
|
||||
nmcli connection modify "$connection" \
|
||||
connection.interface-name "$interface" \
|
||||
802-11-wireless.mode ap \
|
||||
802-11-wireless.band bg \
|
||||
802-11-wireless.channel 6 \
|
||||
802-11-wireless.ssid "$ssid" \
|
||||
802-11-wireless-security.key-mgmt wpa-psk \
|
||||
802-11-wireless-security.proto rsn \
|
||||
802-11-wireless-security.pairwise ccmp \
|
||||
802-11-wireless-security.group ccmp \
|
||||
802-11-wireless-security.pmf 1 \
|
||||
802-11-wireless-security.psk "$passphrase" \
|
||||
ipv4.method shared \
|
||||
ipv4.addresses "$cidr" \
|
||||
ipv6.method ignore \
|
||||
connection.autoconnect yes
|
||||
}
|
||||
|
||||
if [ -r "$config" ]; then
|
||||
ssid=$(python3 -c 'import json,sys; data=json.load(open(sys.argv[1])); print(data.get("control",{}).get("ap_ssid","Vamp Control"))' "$config")
|
||||
passphrase=$(python3 -c 'import json,sys; data=json.load(open(sys.argv[1])); print(data.get("control",{}).get("ap_passphrase","vamp-control"))' "$config")
|
||||
interface=$(python3 -c 'import json,sys; data=json.load(open(sys.argv[1])); print(data.get("control",{}).get("ap_interface","wlan0"))' "$config")
|
||||
cidr=$(python3 -c 'import json,sys; data=json.load(open(sys.argv[1])); print(data.get("control",{}).get("zero_cidr","192.168.42.1/24"))' "$config")
|
||||
fi
|
||||
|
||||
if nmcli -t -f NAME connection show | grep -Fxq "$connection"; then
|
||||
configure_connection
|
||||
else
|
||||
nmcli connection add type wifi ifname "$interface" con-name "$connection" autoconnect yes ssid "$ssid"
|
||||
configure_connection
|
||||
fi
|
||||
|
||||
nmcli connection up "$connection"
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
container_name=${PRODUCT_VAMP_ZERO_CONTAINER:-product-vamp-zero}
|
||||
image_tag=${PRODUCT_VAMP_ZERO_IMAGE:-product-vamp-zero:dev}
|
||||
config_dir=${PRODUCT_VAMP_CONFIG_DIR:-/etc/product-vamp}
|
||||
state_dir=${PRODUCT_VAMP_STATE_DIR:-/var/lib/product-vamp}
|
||||
run_dir=${PRODUCT_VAMP_RUN_DIR:-/run/product-vamp}
|
||||
display_tty=${PRODUCT_VAMP_DISPLAY_TTY:-/dev/tty1}
|
||||
|
||||
install -d -m 0755 "$run_dir"
|
||||
|
||||
if command -v chvt >/dev/null 2>&1 && [ -c "$display_tty" ]; then
|
||||
tty_number=${display_tty#/dev/tty}
|
||||
case "$tty_number" in
|
||||
''|*[!0-9]*)
|
||||
;;
|
||||
*)
|
||||
chvt "$tty_number" || true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [ -c "$display_tty" ]; then
|
||||
if command -v setterm >/dev/null 2>&1; then
|
||||
setterm --cursor off > "$display_tty" || printf '\033[?25l' > "$display_tty" || true
|
||||
else
|
||||
printf '\033[?25l' > "$display_tty" || true
|
||||
fi
|
||||
fi
|
||||
|
||||
docker rm -f "$container_name" >/dev/null 2>&1 || true
|
||||
|
||||
echo "Starting Product Vamp Zero container '$container_name' from '$image_tag' on '$display_tty'"
|
||||
|
||||
exec docker run --rm --name "$container_name" --network host --privileged \
|
||||
--env PRODUCT_VAMP_DISPLAY_TTY="$display_tty" \
|
||||
-v "$config_dir:/etc/product-vamp:ro" \
|
||||
-v "$state_dir:/var/lib/product-vamp" \
|
||||
-v "$run_dir:/run/product-vamp" \
|
||||
"$image_tag" \
|
||||
sh -lc 'display_tty=${PRODUCT_VAMP_DISPLAY_TTY:-/dev/tty1}; exec setsid --wait --ctty /usr/bin/vamp-zero --config /etc/product-vamp/vamp.json < "$display_tty"'
|
||||
Reference in New Issue
Block a user