Skip to content

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 0103. 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:

sudo -u ironshep /opt/ironshep-core/ironshep-core \
  --config /etc/ironshep/core.toml --init-db

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:

  1. Update the copy in both repos identically.
  2. 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/rustc ever panic with "couldn't get the current directory of the process", the repo's parent folder is a dataless cloud-sync (Drive) placeholder denying getcwd. 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