deploy: SSH roll to linuxuser@elektrine.com with shared Docker network
Add scripts/deploy.sh to build/start Magpie and ensure it joins elektrine-magpie-shared (alias magpie) so Elektrine can reach magpie:8090. Forgejo Actions rsyncs and runs the script on every main push.
This commit is contained in:
parent
9cd56a7770
commit
aa43ce2562
3 changed files with 164 additions and 0 deletions
81
.forgejo/workflows/deploy.yml
Normal file
81
.forgejo/workflows/deploy.yml
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
# Deploy Magpie to production via SSH (linuxuser@elektrine.com).
|
||||||
|
# Joins Docker network elektrine-magpie-shared so Elektrine app/worker/caddy
|
||||||
|
# resolve magpie:8090. Secrets: DEPLOY_SSH_KEY, DEPLOY_SSH_HOST_KEY
|
||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: magpie-deploy
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: Deploy over SSH
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: []
|
||||||
|
# Run after CI if both fire on same push — use a local test job first
|
||||||
|
steps:
|
||||||
|
- uses: https://data.forgejo.org/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Go test
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
case "$GITHUB_WORKSPACE" in
|
||||||
|
/data/*) HOST_WS="/opt/forgejo-runner/data${GITHUB_WORKSPACE#/data}" ;;
|
||||||
|
*) HOST_WS="$GITHUB_WORKSPACE" ;;
|
||||||
|
esac
|
||||||
|
docker run --rm --network host \
|
||||||
|
-v "${HOST_WS}:/src" -w /src -e CGO_ENABLED=0 \
|
||||||
|
golang:1.25-bookworm \
|
||||||
|
sh -c "go test ./..."
|
||||||
|
|
||||||
|
- name: Configure SSH
|
||||||
|
env:
|
||||||
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||||
|
DEPLOY_SSH_HOST_KEY: ${{ secrets.DEPLOY_SSH_HOST_KEY || '66.42.127.87 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM5Vx8UDcqvgmBwDs5SlCHd8/oGDoQytGHhbbp4LNK4o' }}
|
||||||
|
DEPLOY_HOST: ${{ vars.DEPLOY_HOST || 'elektrine.com' }}
|
||||||
|
DEPLOY_PORT: ${{ vars.DEPLOY_PORT || '22' }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
install -d -m 0700 ~/.ssh
|
||||||
|
printf '%s\n' "$DEPLOY_SSH_KEY" | sed 's/\r$//' | sed 's/\\n/\n/g' > ~/.ssh/id_ed25519
|
||||||
|
chmod 0600 ~/.ssh/id_ed25519
|
||||||
|
: > ~/.ssh/known_hosts
|
||||||
|
printf '%s\n' "$DEPLOY_SSH_HOST_KEY" | sed 's/\r$//' | sed 's/\\n/\n/g' >> ~/.ssh/known_hosts
|
||||||
|
ssh-keyscan -p "$DEPLOY_PORT" -T 5 -t ed25519,rsa "$DEPLOY_HOST" 2>/dev/null >> ~/.ssh/known_hosts || true
|
||||||
|
chmod 0600 ~/.ssh/known_hosts
|
||||||
|
ssh -p "$DEPLOY_PORT" \
|
||||||
|
-i "$HOME/.ssh/id_ed25519" \
|
||||||
|
-o BatchMode=yes -o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=yes \
|
||||||
|
-o UserKnownHostsFile="$HOME/.ssh/known_hosts" \
|
||||||
|
"${{ vars.DEPLOY_USER || 'linuxuser' }}@$DEPLOY_HOST" 'echo ssh_ok; hostname; id'
|
||||||
|
|
||||||
|
- name: Rsync and deploy
|
||||||
|
env:
|
||||||
|
DEPLOY_HOST: ${{ vars.DEPLOY_HOST || 'elektrine.com' }}
|
||||||
|
DEPLOY_USER: ${{ vars.DEPLOY_USER || 'linuxuser' }}
|
||||||
|
DEPLOY_PORT: ${{ vars.DEPLOY_PORT || '22' }}
|
||||||
|
DEPLOY_PATH: ${{ vars.DEPLOY_PATH || '/opt/magpie' }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
RSYNC_RSH="ssh -p ${DEPLOY_PORT} -i ${HOME}/.ssh/id_ed25519 -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=${HOME}/.ssh/known_hosts"
|
||||||
|
# Preserve production secrets and data mounts
|
||||||
|
rsync -az --delete \
|
||||||
|
-e "$RSYNC_RSH" \
|
||||||
|
--exclude '.git/' \
|
||||||
|
--exclude '.env.production' \
|
||||||
|
--exclude 'dist/' \
|
||||||
|
--exclude 'magpie' \
|
||||||
|
./ "${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/"
|
||||||
|
ssh -p "$DEPLOY_PORT" \
|
||||||
|
-i "$HOME/.ssh/id_ed25519" \
|
||||||
|
-o BatchMode=yes -o IdentitiesOnly=yes \
|
||||||
|
-o StrictHostKeyChecking=yes \
|
||||||
|
-o UserKnownHostsFile="$HOME/.ssh/known_hosts" \
|
||||||
|
"${DEPLOY_USER}@${DEPLOY_HOST}" \
|
||||||
|
"chmod +x ${DEPLOY_PATH}/scripts/deploy.sh && cd ${DEPLOY_PATH} && ./scripts/deploy.sh"
|
||||||
22
README.md
22
README.md
|
|
@ -269,3 +269,25 @@ make release
|
||||||
```
|
```
|
||||||
|
|
||||||
Artifacts are written to `dist/`, with checksums in `dist/SHA256SUMS`.
|
Artifacts are written to `dist/`, with checksums in `dist/SHA256SUMS`.
|
||||||
|
|
||||||
|
## Production deploy (same host as Elektrine)
|
||||||
|
|
||||||
|
Magpie runs as a separate Compose project on the Elektrine host and joins the
|
||||||
|
shared Docker network `elektrine-magpie-shared` so Elektrine services can reach
|
||||||
|
`http://magpie:8090`.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# on the server (linuxuser)
|
||||||
|
cd /opt/magpie
|
||||||
|
./scripts/deploy.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Forgejo Actions (push to `main`) rsyncs to `linuxuser@elektrine.com:/opt/magpie`
|
||||||
|
and runs that script. Elektrine deploy re-attaches Magpie to the shared network
|
||||||
|
every time via `ensure_magpie_shared_network`.
|
||||||
|
|
||||||
|
Required on the host:
|
||||||
|
|
||||||
|
- `/opt/magpie/.env.production` (not in git)
|
||||||
|
- Docker (or passwordless `sudo docker`) for `linuxuser`
|
||||||
|
- Shared network name: `MAGPIE_DOCKER_NETWORK` (default `elektrine-magpie-shared`)
|
||||||
|
|
|
||||||
61
scripts/deploy.sh
Executable file
61
scripts/deploy.sh
Executable file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Deploy Magpie on the same host as Elektrine and join the shared Docker network
|
||||||
|
# so app/worker/caddy can reach http://magpie:8090.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
NETWORK_NAME="${MAGPIE_DOCKER_NETWORK:-elektrine-magpie-shared}"
|
||||||
|
CONTAINER_NAME="${MAGPIE_CONTAINER_NAME:-magpie}"
|
||||||
|
COMPOSE_FILES=(-f docker-compose.yml -f docker-compose.network.yml)
|
||||||
|
|
||||||
|
if docker info >/dev/null 2>&1; then
|
||||||
|
DOCKER=(docker)
|
||||||
|
elif sudo -n docker info >/dev/null 2>&1; then
|
||||||
|
DOCKER=(sudo -n docker)
|
||||||
|
else
|
||||||
|
echo "No docker access (need docker group or passwordless sudo docker)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f .env.production ]]; then
|
||||||
|
echo "Missing $ROOT_DIR/.env.production" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export MAGPIE_DOCKER_NETWORK="$NETWORK_NAME"
|
||||||
|
|
||||||
|
echo "Info: ensuring shared network $NETWORK_NAME" >&2
|
||||||
|
"${DOCKER[@]}" network inspect "$NETWORK_NAME" >/dev/null 2>&1 \
|
||||||
|
|| "${DOCKER[@]}" network create "$NETWORK_NAME" >/dev/null
|
||||||
|
|
||||||
|
echo "Info: building and starting Magpie" >&2
|
||||||
|
"${DOCKER[@]}" compose "${COMPOSE_FILES[@]}" build
|
||||||
|
"${DOCKER[@]}" compose "${COMPOSE_FILES[@]}" up -d --force-recreate --remove-orphans
|
||||||
|
|
||||||
|
# Compose should attach via docker-compose.network.yml; re-connect with alias if needed
|
||||||
|
# (force-recreate can drop a manually-connected endpoint).
|
||||||
|
attached="$("${DOCKER[@]}" inspect "$CONTAINER_NAME" --format \
|
||||||
|
"{{if index .NetworkSettings.Networks \"$NETWORK_NAME\"}}yes{{end}}" 2>/dev/null || true)"
|
||||||
|
if [[ "$attached" != "yes" ]]; then
|
||||||
|
echo "Info: connecting $CONTAINER_NAME to $NETWORK_NAME as alias magpie" >&2
|
||||||
|
"${DOCKER[@]}" network connect --alias magpie "$NETWORK_NAME" "$CONTAINER_NAME"
|
||||||
|
else
|
||||||
|
# Ensure the magpie DNS alias exists (network connect --alias is idempotent only if already set)
|
||||||
|
echo "Info: $CONTAINER_NAME already on $NETWORK_NAME" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Info: Magpie status" >&2
|
||||||
|
"${DOCKER[@]}" compose "${COMPOSE_FILES[@]}" ps
|
||||||
|
"${DOCKER[@]}" inspect "$CONTAINER_NAME" --format \
|
||||||
|
'networks={{range $k,$v := .NetworkSettings.Networks}}{{$k}}({{join $v.Aliases ","}}) {{end}}'
|
||||||
|
|
||||||
|
# Quick health: S3 endpoint listens on loopback
|
||||||
|
if command -v curl >/dev/null 2>&1; then
|
||||||
|
if curl -sf -o /dev/null --max-time 3 "http://127.0.0.1:8090/" || true; then
|
||||||
|
echo "Info: Magpie is listening on 127.0.0.1:8090" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "DEPLOY_OK"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue