This guide deploys zephyr-simulator-server on one droplet and supports in-place source-code upgrades with rollback.
Install prerequisites:
sudo apt-get update
sudo apt-get install -y ca-certificates curl git
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"
newgrp dockerOpen ports 22, 80, 443 in both:
- DigitalOcean networking firewall
- Host firewall (ufw or equivalent)
sudo mkdir -p /srv
cd /srv
git clone https://github.com/beriberikix/zephyr-simulator-server.git
cd zephyr-simulator-server
cp .env.production.example .env.productionEdit .env.production:
DOMAIN=coap.cloudACME_EMAIL=jmberi@gmail.comRUNTIME_NAME=runsc(orruncif gVisor is unavailable)BACKEND_IMAGE_REPO=ghcr.io/beriberikix/zephyr-simulator-server-backendBACKEND_IMAGE_TAG=latest(or a specific commit SHA tag for pinned releases)
Backend images are built in GitHub Actions and published to GHCR:
- Workflow:
.github/workflows/build-backend-image.yml - Published tags:
latest${GITHUB_SHA}
For production safety, prefer sha-pinned tags in .env.production.
Set coap.cloud DNS record to the droplet IP as DNS only (gray cloud).
Keep Cloudflare SSL mode at Full (strict); proxy can be re-enabled after first successful issuance.
./scripts/deploy/deploy_prod.shWhat this does:
- Builds emulator image locally
- Pulls backend image from GHCR
- Starts stack with production compose overlay
- Runs local health checks through Caddy
- Records known-good commit in
.deploy/known_good_commit
If GHCR package visibility is private, authenticate once on droplet:
docker login ghcr.iocurl -fsS https://coap.cloud/health
curl -fsS https://coap.cloud/api/healthAfter success, switch DNS record to Proxied (orange cloud).
Run on the droplet from repository root:
./scripts/deploy/upgrade_prod.shWhat this does:
- Stores current commit in
.deploy/previous_commit - Stores current backend image in
.deploy/previous_backend_image - Fast-forwards local
mainfromorigin/main - Pulls configured backend image and redeploys
- Verifies health checks
If upgrade verification fails, run:
./scripts/deploy/rollback_prod.shWhat this does:
- Checks out
.deploy/previous_commit - Reapplies
.deploy/previous_backend_image(if present) - Redeploys that commit
- Re-runs health checks
docker exec zephyr-backend ./server superuser upsert admin@example.com 'strong-password'- App data is stored in
./data(host-mounted volume). - Caddy certificates are stored in
caddy_dataDocker volume. - Rollback script checks out a specific commit and may leave git in detached HEAD state. To return to branch tracking after rollback, use:
git checkout main