diff --git a/.env b/.env new file mode 100644 index 0000000..f0f988a --- /dev/null +++ b/.env @@ -0,0 +1,31 @@ +#:CONFIGURATION FILE FOR BEARCLOUD +#:WARNING: DO NOT EDIT FILEPATH COMMENTS WITHOUT CONSENT OF substitution.sh +# /etc/hostname +CLOUD_HOSTNAME=localhost + +# /etc/network/interfaces +CLOUD_GATEWAY_ADDRESS=10.0.0.119 + +# /root/.ssh/authorized_keys +HOST_SSH_PUBLIC_KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN6GbswtvLbhmju/vBunpfPaqpcIuESJSLoR+Sz0ujTs cardno:F1D0_013135A1 + +# /etc/ssh/sshd_config.d/09-adjust-ssh-port.conf +HOST_SSH_PORT=2222 + +# /daemon/config.yaml +BUBBLE_SSH_PORT=22 + +# /etc/init.d/auth-server +BUBBLE_AUTH_ORG=cloud +BUBBLE_AUTH_TEAM=workspace +BUBBLE_AUTH_GITEA_URL=https://git.sfclub.cc + +# /etc/conf.d/auth-server +BUBBLE_AUTH_GITEA_KEY=sk-xxxxxxxx + +# /usr/bin/tsdns +TS_AUTHKEY= +HOMELAB_TLD=ice +HOMELAB_ZONE=cloud +ADVERTISE_ROUTE=10.1.0.0/24 +TSDNS_SUBNET=10.1.0.0/24 \ No newline at end of file diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f0f988a --- /dev/null +++ b/.env.example @@ -0,0 +1,31 @@ +#:CONFIGURATION FILE FOR BEARCLOUD +#:WARNING: DO NOT EDIT FILEPATH COMMENTS WITHOUT CONSENT OF substitution.sh +# /etc/hostname +CLOUD_HOSTNAME=localhost + +# /etc/network/interfaces +CLOUD_GATEWAY_ADDRESS=10.0.0.119 + +# /root/.ssh/authorized_keys +HOST_SSH_PUBLIC_KEY=ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN6GbswtvLbhmju/vBunpfPaqpcIuESJSLoR+Sz0ujTs cardno:F1D0_013135A1 + +# /etc/ssh/sshd_config.d/09-adjust-ssh-port.conf +HOST_SSH_PORT=2222 + +# /daemon/config.yaml +BUBBLE_SSH_PORT=22 + +# /etc/init.d/auth-server +BUBBLE_AUTH_ORG=cloud +BUBBLE_AUTH_TEAM=workspace +BUBBLE_AUTH_GITEA_URL=https://git.sfclub.cc + +# /etc/conf.d/auth-server +BUBBLE_AUTH_GITEA_KEY=sk-xxxxxxxx + +# /usr/bin/tsdns +TS_AUTHKEY= +HOMELAB_TLD=ice +HOMELAB_ZONE=cloud +ADVERTISE_ROUTE=10.1.0.0/24 +TSDNS_SUBNET=10.1.0.0/24 \ No newline at end of file diff --git a/BUILD.sh b/BUILD.sh index 793e0e2..1eb5f87 100755 --- a/BUILD.sh +++ b/BUILD.sh @@ -2,8 +2,6 @@ set -eo pipefail -hasunset=0 - if [ "$UID" != "0" ]; then echo "This script must be run in root." exit 2 @@ -16,29 +14,11 @@ fi PATH="$PWD/scripts:$PATH" -if [[ "$CLOUD_CONFIG_REPO" -eq "" ]]; then - echo "CLOUD_CONFIG_REPO is not set." - CLOUD_CONFIG_REPO="https://git.sfclub.cc/cloud/bearnet" - hasunset=1 -fi +validate.sh -if [[ "$CLOUD_CONFIG_REVISION" -eq "" ]]; then - echo "CLOUD_CONFIG_REVISION is not set." - CLOUD_CONFIG_REVISION="wish" - hasunset=1 -fi - -if [[ "$CLOUD_GATEWAY_ADDRESS" -eq "" ]]; then - echo "CLOUD_GATEWAY_ADDRESS is not set." - CLOUD_GATEWAY_ADDRESS="10.0.0.119" - hasunset=1 -fi - -if [[ "$hasunset" -ne 0 ]]; then - echo "" - echo "Default values will be used for unset environments:" - echo "" - set | grep -E "^CLOUD_" +if [[ "$?" != "0" ]]; then + echo "env validation failed" + exit 1 fi IMAGE_TAG=$(git rev-parse --short HEAD) diff --git a/image/build-image.sh b/image/build-image.sh index 386e139..969798e 100755 --- a/image/build-image.sh +++ b/image/build-image.sh @@ -31,7 +31,7 @@ alpine-make-vm-image \ --fs-skel-dir "$OVERLAY_DIR" \ --fs-skel-chown root:root \ --script-chroot \ - --packages "git curl docker cronie openssh" \ + --packages "curl docker openssh" \ "$IMAGE_FILE" \ "$CONFIGURE_SH" | tee $TMP diff --git a/image/configure.sh b/image/configure.sh index 706791f..f190aff 100755 --- a/image/configure.sh +++ b/image/configure.sh @@ -31,7 +31,6 @@ rc-update add net.lo boot rc-update add net.eth0 default rc-update add acpid default rc-update add docker default -rc-update add cronie default rc-update add sshd rc-update add auth-server rc-update add bubble @@ -48,12 +47,5 @@ rm -rf \ /usr/share/doc \ /usr/share/info -step 'Setup git user' -git config --global user.email bearnet+keeper@sab.ee -git config --global user.name "B.B.K.K.B.K.K" -adduser -S keeper -mkdir /users -chown keeper /users - echo '' echo '=== Configure script completed ===' diff --git a/image/overlay/daemon/config.yaml b/image/overlay/daemon/config.yaml new file mode 100644 index 0000000..f546cca --- /dev/null +++ b/image/overlay/daemon/config.yaml @@ -0,0 +1,14 @@ +address: ":_BUBBLE_SSH_PORT_" +network-group: "workspace" +server-key-file: "/etc/ssh/ssh_host_rsa_key" + +workspace-parent: "/data/workspace" +global-share-dir: "/data/share" +auth-server: "http://localhost:8080/" + +manager: + address: "0.0.0.0:7684" + +templates: + ".*": + image: "" diff --git a/image/overlay/daemon/update-keys.sh b/image/overlay/daemon/update-keys.sh deleted file mode 100755 index 8a82cca..0000000 --- a/image/overlay/daemon/update-keys.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh -# VARIABLES: _REVISION_ _REPO_ - -set -euo pipefail -mkdir -p /users && chown keeper /users && chmod 644 /users - -init_repo(){ - su - keeper 'git clone -b _REVISION_ _REPO_ /users' -} - -if [[ ! -d /users/.git ]]; then - init_repo -elif [[ -d /users && cd /users && ! su - keeper 'git pull origin _REVISION_' ]]; then - init_repo -fi \ No newline at end of file diff --git a/image/overlay/etc/conf.d/auth-server b/image/overlay/etc/conf.d/auth-server new file mode 100644 index 0000000..387872b --- /dev/null +++ b/image/overlay/etc/conf.d/auth-server @@ -0,0 +1 @@ +GITEA_TOKEN=_BUBBLE_AUTH_GITEA_KEY_ \ No newline at end of file diff --git a/image/overlay/etc/hostname b/image/overlay/etc/hostname new file mode 100644 index 0000000..e12d995 --- /dev/null +++ b/image/overlay/etc/hostname @@ -0,0 +1 @@ +_CLOUD_HOSTNAME_ \ No newline at end of file diff --git a/image/overlay/etc/init.d/auth-server b/image/overlay/etc/init.d/auth-server index e925207..f9cc2cf 100755 --- a/image/overlay/etc/init.d/auth-server +++ b/image/overlay/etc/init.d/auth-server @@ -1,7 +1,7 @@ #!/sbin/openrc-run command="/usr/bin/auth-server" command_background=true -command_args="-addr 0.0.0.0:8080 -root /users" +command_args="-org _BUBBLE_AUTH_ORG_ -team _BUBBLE_AUTH_TEAM_ -gitea-url _BUBBLE_AUTH_GITEA_URL_" command_user="keeper" pidfile="/run/${RC_SVCNAME}.pid" diff --git a/image/overlay/etc/init.d/tsdns b/image/overlay/etc/init.d/tsdns new file mode 100755 index 0000000..5831fc1 --- /dev/null +++ b/image/overlay/etc/init.d/tsdns @@ -0,0 +1,9 @@ +#!/sbin/openrc-run + +depend() { + need docker net +} + +command="/usr/bin/tsdns" +command_background=true +pidfile="/run/${RC_SVCNAME}.pid" diff --git a/image/overlay/etc/init.d/update-images b/image/overlay/etc/init.d/update-images new file mode 100755 index 0000000..9e7e683 --- /dev/null +++ b/image/overlay/etc/init.d/update-images @@ -0,0 +1,7 @@ +#!/sbin/openrc-run + +depend() { + need docker net +} + +command="/usr/bin/update-images" diff --git a/image/overlay/etc/network/interfaces b/image/overlay/etc/network/interfaces index 790f947..9ff91a0 100644 --- a/image/overlay/etc/network/interfaces +++ b/image/overlay/etc/network/interfaces @@ -3,4 +3,4 @@ iface lo inet loopback auto eth0 iface eth0 inet dhcp - post-up ip route del default || true; ip route add default via GATEWAY_ADDRESS + post-up ip route del default || true; ip route add default via _CLOUD_GATEWAY_ADDRESS_ diff --git a/image/overlay/etc/ssh/sshd_config.d/09-adjust-ssh-port.conf b/image/overlay/etc/ssh/sshd_config.d/09-adjust-ssh-port.conf new file mode 100644 index 0000000..0f7a63d --- /dev/null +++ b/image/overlay/etc/ssh/sshd_config.d/09-adjust-ssh-port.conf @@ -0,0 +1 @@ +Port _HOST_SSH_PORT_ diff --git a/image/overlay/root/.ssh/authorized_keys b/image/overlay/root/.ssh/authorized_keys index 71250e2..27513ca 100644 --- a/image/overlay/root/.ssh/authorized_keys +++ b/image/overlay/root/.ssh/authorized_keys @@ -1 +1 @@ -ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN6GbswtvLbhmju/vBunpfPaqpcIuESJSLoR+Sz0ujTs cardno:F1D0_013135A1 +_HOST_SSH_PUBLIC_KEY_ \ No newline at end of file diff --git a/image/overlay/usr/bin/tsdns b/image/overlay/usr/bin/tsdns new file mode 100755 index 0000000..26f04e2 --- /dev/null +++ b/image/overlay/usr/bin/tsdns @@ -0,0 +1,23 @@ +#!/bin/sh + + +if [ ! docker network insepct "workspace" ]; then + docker network create \ + --attachable \ + --ipv4 \ + --ip-range "_ADVERTISE_ROUTE_" \ + --subnet "_TSDNS_SUBNET_" \ + workspace +fi + +docker run -e "TS_AUTHKEY=_TS_AUTHKEY_" \ + -e "HOMELAB_TLD=_HOMELAB_TLD_" \ + -e "HOMELAB_ZONE=_HOMELAB_ZONE_" \ + -e "TS_STATE_DIR=/tstate" \ + -e "ADVERTISE_ROUTE=_ADVERTISE_ROUTE_" \ + -e "TS_DEBUG_OMIT_LOCAL_ADDRS=true" \ + --network "workspace" \ + -p 41641:41641/udp + -v "/data/tsdns:/tstate" + --restart unless-stopped + ghcr.io/saltedfishclub/tsdns:latest diff --git a/image/overlay/usr/bin/update-images b/image/overlay/usr/bin/update-images new file mode 100755 index 0000000..6a7d3e1 --- /dev/null +++ b/image/overlay/usr/bin/update-images @@ -0,0 +1,10 @@ +#!/bin/sh + +cleanup_() { + touch /.image-update-flag +} + +if [ ! -f /.image-update-flag ]; then + docker pull +fi + diff --git a/image/overlay/var/spool/cron/crontabs/root b/image/overlay/var/spool/cron/crontabs/root deleted file mode 100644 index e972907..0000000 --- a/image/overlay/var/spool/cron/crontabs/root +++ /dev/null @@ -1,2 +0,0 @@ -# min hour day month weekday command -*/15 * * * * /usr/bin/sh /daemon/update-keys.sh \ No newline at end of file diff --git a/image/substitution.sh b/image/substitution.sh new file mode 100755 index 0000000..e4473d1 --- /dev/null +++ b/image/substitution.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +current_file="" +root="/kitchen/overlay" + +while IFS= read -r line; do + case "$line" in + \#\ /*) + current_file="${line#\# }" + ;; + \#\:*) + continue + ;; + *=*) + if [ -z "$current_file" ]; then + echo "warning: value without file: $line" >&2 + continue + fi + key="${line%%=*}" + value="${line#*=}" + key_esc=$(printf '%s' "$key" | sed 's/[]\/$*.^[]/\\&/g') + value_esc=$(printf '%s' "$value" | sed 's/[\/&]/\\&/g') + sed -i "s/_${key_esc}_/${value_esc}/g" "$root$current_file" + ;; + "") + continue + ;; + *) + echo "unknown line: $line" >&2 + ;; + esac +done \ No newline at end of file diff --git a/scripts/validate.sh b/scripts/validate.sh new file mode 100755 index 0000000..41e381c --- /dev/null +++ b/scripts/validate.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +root="$PWD/image/overlay" +env_file="${1:-.env}" + +if [ ! -f "$env_file" ]; then + echo "cannot find $env_file" + exit 1 +fi + +current_file="" + +fail=0 + +while IFS= read -r line; do + case "$line" in + \#\ /*) + current_file="${line#\# }" + + target="$root$current_file" + + if [ ! -f "$target" ]; then + echo "missing file: $target" >&2 + fail=1 + current_file="" + fi + ;; + \#\:*) + continue + ;; + *=*) + if [ -z "$current_file" ]; then + echo "warning: value without file: $line" >&2 + continue + fi + + key="${line%%=*}" + + target="$root$current_file" + + if ! grep -q "_${key}_" "$target"; then + echo "missing variable: _${key}_ in $target" >&2 + fail=1 + fi + ;; + + "") + continue + ;; + + *) + echo "unknown line: $line" >&2 + fail=1 + ;; + esac +done < "$env_file" + +exit "$fail" \ No newline at end of file diff --git a/vm.Dockerfile b/vm.Dockerfile index 08671ee..579d82f 100644 --- a/vm.Dockerfile +++ b/vm.Dockerfile @@ -3,22 +3,18 @@ FROM golang:1.25-alpine AS bubble-builder WORKDIR /src RUN apk add git && git clone https://github.com/iceBear67/bubble . && go mod download && mkdir /build RUN CGO_ENABLED=0 go build -o /build/daemon . && \ - CGO_ENABLED=0 go build -o /build/auth_server ./util/ + CGO_ENABLED=0 go build -o /build/auth_server ./gitea-auth/ RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ go build -o /build/daemon . && \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \ - go build -o /build/auth_server ./util/ + go build -o /build/auth_server ./gitea-auth/ FROM alpine:3.24 AS rootfs-builder -ENV CLOUD_CONFIG_REPO="https://git.sfclub.cc/cloud/bearnet" -ENV CLOUD_CONFIG_REVISION="wish" -ENV CLOUD_GATEWAY_ADDRESS="10.0.0.119" RUN apk update && apk add alpine-make-vm-image COPY ./image /kitchen -RUN sed -i "s#_REPO_#$CLOUD_CONFIG_REPO#g" /kitchen/overlay/daemon/update-keys.sh && \ - sed -i "s#_REVISION_#$CLOUD_CONFIG_REVISION#g" /kitchen/overlay/daemon/update-keys.sh && \ - sed -i "s#GATEWAY_ADDRESS#$CLOUD_GATEWAY_ADDRESS#g" /kitchen/overlay/etc/network/interfaces +COPY .env /kitchen/.env +RUN sh /kitchen/substitution.sh < /kitchen/.env COPY --from=bubble-builder --chmod=755 /build/daemon /kitchen/overlay/usr/bin/bubble COPY --from=bubble-builder --chmod=755 /build/auth_server /kitchen/overlay/usr/bin/auth-server COPY ./secret/* /kitchen/overlay/etc/ssh/