Redeploying after a code change¶
How to push a change to ironshep-core or ironshep-edge onto a host that's
already running the initial install from 01–03. Not host-specific — the
core steps run on the core host, the edge steps on each edge host.
Nothing here touches certificates or the database password — those are set once at install and survive a redeploy. A code change is: rebuild the binary, swap it in, restart the service.
The services stop gracefully. Their systemd units set KillSignal=SIGTERM
and TimeoutStopSec=30, and both binaries flush on SIGTERM — so
systemctl restart lets the edge ship whatever it still has buffered and lets
core drain its write queue before the new binary starts. You don't lose
in-flight data across a normal restart.
Core¶
On the core host, in your ironshep-core git checkout:
git pull # or check out the revision you want
cargo build --release --locked # --locked = the tested dependency set
Swap the binary in and restart. Use a temp-name + mv so replacing the
running binary can't fail with "Text file busy":
sudo cp target/release/ironshep-core /opt/ironshep-core/ironshep-core.new
sudo mv /opt/ironshep-core/ironshep-core.new /opt/ironshep-core/ironshep-core
sudo chown ironshep:ironshep /opt/ironshep-core/ironshep-core
sudo systemctl restart ironshep-core
Watch it come back up:
systemctl status ironshep-core --no-pager
journalctl -u ironshep-core -f # expect: "listening on 0.0.0.0:50051"
While core is down (a second or two), edges buffer locally and reconnect on
their own — the same resilience you can watch in POC_LAB.md step 6.
UI-only changes count as core changes. app.js, style.css, and the HTML
are compiled into the binary (include_str!), so a console tweak still needs
the rebuild + swap + restart above. There is no separate front-end deploy.
If the schema changed, apply it after deploying — it's idempotent and
additive (CREATE TABLE/INDEX IF NOT EXISTS, columns with defaults), so it's
safe to run on a populated database:
Additive changes need nothing more. A destructive change (dropping or
renaming a column, tightening a constraint) is not handled by --init-db —
write and run the ALTER TABLE yourself first. See the shepherd-poc migration
note in ironshep-core/docs/SETUP_RHEL9.md for the pattern.
Edge¶
On each edge host, in your ironshep-edge git checkout:
git pull
cargo build --release --locked
sudo cp target/release/ironshep-edge /opt/ironshep-edge/ironshep-edge.new
sudo mv /opt/ironshep-edge/ironshep-edge.new /opt/ironshep-edge/ironshep-edge
sudo chown ironshep:ironshep /opt/ironshep-edge/ironshep-edge
sudo systemctl restart ironshep-edge
systemctl status ironshep-edge --no-pager
journalctl -u ironshep-edge -f # expect a listener line per protocol,
# then "connected to core at https://…"
bash scripts/edge_healthcheck.sh --verbose # or the health-check script
The edge holds no database, so there's no schema step. On restart its in-memory buffer flushes to core first (the SIGTERM behaviour above); anything that can't flush in 30s is dropped, which at POC volumes is effectively never.
If OPC-UA ever blocks the build, cargo build --release --locked --no-default-features
compiles everything else.
When the wire contract changed¶
proto/ingest.proto is duplicated in both repos and must stay in sync. If
your change touched it:
- Update the copy in both repos identically.
- Rebuild and redeploy both core and edge.
proto3 evolution rules keep a version skew safe if you followed them — only add fields, never reuse or renumber a tag. Under that rule a newer edge talking to an older core (or vice versa) still works, so you can redeploy the two hosts one at a time without a coordinated outage. Renumbering or repurposing a field breaks that — don't.
Rollback¶
Keep the previous binary before you overwrite it, and rollback is a swap back:
# before deploying:
sudo cp /opt/ironshep-core/ironshep-core /opt/ironshep-core/ironshep-core.prev
# to roll back:
sudo mv /opt/ironshep-core/ironshep-core.prev /opt/ironshep-core/ironshep-core
sudo systemctl restart ironshep-core
Or rebuild from the previous revision: git checkout <prev-tag> →
cargo build --release --locked → swap → restart. Because Cargo.lock is
committed, an older revision rebuilds with exactly the dependencies it shipped
with.
A schema that already advanced won't roll back with the binary — additive columns are harmless to an older binary (it just ignores them), so this is rarely a problem in practice.
Local dev (single Mac)¶
No systemd. Rebuild and bounce the stack with the automation scripts:
cd Code/ironshep-automation/scritps
# after editing core and/or edge:
bash ironshep-start.sh --build # --build rebuilds both, then (re)starts
# or, if already running, restart just what changed:
bash ironshep-stop.sh && bash ironshep-start.sh --sim
ironshep-start.sh --build runs cargo build --locked on both repos before
launching, so it picks up your change. See 00-local-mac.md for the full
local workflow.
Build gotcha (macOS + cloud-synced repo): if
cargo/rustcever panic with "couldn't get the current directory of the process", the repo's parent folder is a dataless cloud-sync (Drive) placeholder denyinggetcwd. Open the folder in Finder to force a sync, or build from a copy under/tmp.
Quick reference¶
| Change | Rebuild | Redeploy | Extra |
|---|---|---|---|
| core logic / UI / config-handling | core | core host | — |
| core schema | core | core host | run --init-db after (additive) or ALTER TABLE (destructive) |
| edge logic / listeners | edge | each edge host | — |
proto/ingest.proto |
both | both hosts | sync the file in both repos first |
| dependency bump | affected repo(s) | affected host(s) | commit the updated Cargo.lock |