Skip to content

ci: require valid DEPLOY_SSH_KEY_B64 and decode robustly #11

ci: require valid DEPLOY_SSH_KEY_B64 and decode robustly

ci: require valid DEPLOY_SSH_KEY_B64 and decode robustly #11

Workflow file for this run

name: Deploy to server
on:
push:
branches: ["main"]
workflow_dispatch: {}
permissions:
contents: read
concurrency:
group: deploy-thingspanel-adapter-http
cancel-in-progress: true
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true
- name: Build
run: |
set -e
go mod tidy
mkdir -p dist
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/thingspanel-adapter-http ./cmd
./dist/thingspanel-adapter-http --help >/dev/null 2>&1 || true
- name: Prepare SSH key
env:
DEPLOY_SSH_KEY_B64: ${{ secrets.DEPLOY_SSH_KEY_B64 }}
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
set -euo pipefail
umask 077
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Create file with safe permissions first (prevents OpenSSH "bad permissions")
install -m 600 /dev/null ~/.ssh/id_ed25519
if [ -n "${DEPLOY_SSH_KEY_B64:-}" ]; then
# Secrets can sometimes pick up whitespace/newlines; sanitize before decoding.
b64_clean="$(printf "%s" "$DEPLOY_SSH_KEY_B64" | tr -d '\r\n ' )"
# Decode (fail hard with a clear message; avoids silently using a broken fallback)
if ! printf "%s" "$b64_clean" | base64 --decode > ~/.ssh/id_ed25519; then
echo "ERROR: DEPLOY_SSH_KEY_B64 is not valid base64. Recreate it with: base64 -w0 /root/.ssh/<your_keyfile>" >&2
exit 1
fi
else
echo "ERROR: DEPLOY_SSH_KEY_B64 secret is empty/missing" >&2
exit 1
fi
chmod 600 ~/.ssh/id_ed25519
ssh-keygen -lf ~/.ssh/id_ed25519 >/dev/null
- name: Upload binary + default config to /tmp (scp)
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || 22 }}
run: |
set -euo pipefail
ssh -p "$DEPLOY_PORT" -o StrictHostKeyChecking=no "$DEPLOY_USER@$DEPLOY_HOST" "mkdir -p /tmp/thingspanel-adapter-http"
scp -P "$DEPLOY_PORT" -o StrictHostKeyChecking=no dist/thingspanel-adapter-http "$DEPLOY_USER@$DEPLOY_HOST:/tmp/thingspanel-adapter-http/thingspanel-adapter-http"
# Upload default config from repo (will only be installed on server if missing)
scp -P "$DEPLOY_PORT" -o StrictHostKeyChecking=no configs/config.yaml "$DEPLOY_USER@$DEPLOY_HOST:/tmp/thingspanel-adapter-http/config.yaml"
- name: Ensure service + restart (sudo)
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || 22 }}
run: |
set -euo pipefail
ssh -p "$DEPLOY_PORT" -o StrictHostKeyChecking=no "$DEPLOY_USER@$DEPLOY_HOST" 'set -e
sudo install -d /opt/thingspanel/bin
sudo install -m 0755 /tmp/thingspanel-adapter-http/thingspanel-adapter-http /opt/thingspanel/bin/thingspanel-adapter-http
# Ensure runtime directory exists (for configs/logs). We do NOT overwrite configs here.
sudo install -d /opt/thingspanel/thingspanel-adapter-http
sudo install -d /opt/thingspanel/thingspanel-adapter-http/configs
# Install default config on first deploy only (do not overwrite user config)
if [ ! -f /opt/thingspanel/thingspanel-adapter-http/configs/config.yaml ]; then
sudo install -m 0644 /tmp/thingspanel-adapter-http/config.yaml /opt/thingspanel/thingspanel-adapter-http/configs/config.yaml
fi
if [ ! -f /etc/systemd/system/thingspanel-adapter-http.service ]; then
sudo tee /etc/systemd/system/thingspanel-adapter-http.service >/dev/null <<"EOF"
[Unit]
Description=ThingsPanel Adapter HTTP
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/thingspanel/thingspanel-adapter-http
ExecStart=/opt/thingspanel/bin/thingspanel-adapter-http --config /opt/thingspanel/thingspanel-adapter-http/configs/config.yaml
Restart=always
RestartSec=3
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable thingspanel-adapter-http
fi
sudo systemctl restart thingspanel-adapter-http
sudo systemctl --no-pager -l status thingspanel-adapter-http || true
sudo journalctl -u thingspanel-adapter-http --no-pager -n 200 || true
'
# Collect remote logs into a downloadable artifact so you don't have to copy/paste.
- name: Collect remote logs
if: ${{ always() }}
env:
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || 22 }}
run: |
set -euo pipefail
mkdir -p artifacts
ssh -p "$DEPLOY_PORT" -o StrictHostKeyChecking=no "$DEPLOY_USER@$DEPLOY_HOST" '(
echo "### date"; date -Is;
echo; echo "### uname"; uname -a;
echo; echo "### systemctl status"; systemctl --no-pager -l status thingspanel-adapter-http || true;
echo; echo "### journalctl (last 400 lines)"; journalctl -u thingspanel-adapter-http --no-pager -n 400 || true;
)' > artifacts/remote-logs.txt
- name: Upload deploy logs artifact
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: deploy-logs
path: artifacts/remote-logs.txt
retention-days: 7