Deployment & Infrastructure
This document covers production deployment processes, container orchestration, network management, and monitoring for the Smart Smoker V2 project.
Version Deployments
Production deploys are cut by merging the release PR that release-please
keeps open on master. That single merge bumps every package.json, updates
CHANGELOG.md, tags vX.Y.Z, publishes the GitHub Release, builds the cloud
images from that tag and deploys production behind a blocking smoke gate. The
deploy job still stops at the production environment gate (required reviewer +
5-minute wait timer) for one approval click; removing that gate is a pending
maintainer settings change.
Do not hand-edit versions, hand-cut tags or draft Releases manually — that path skips the changelog and the version bumps. See Release Process for the full flow, and Manual Deployment Runbook for the re-deploy/rollback escape hatches.
Container Deployment
Smoker Environment
Containers for the smoker are handled by watchtower on the device. It polls every 300s
and replaces the running containers when the image behind :latest changes.
Two things bound that, and both matter:
:latestonly moves when a GitHub Release is published. Nightly builds publish:nightly, which the physical device must never run — those bundles are built pointing at dev-cloud. Merging to master never updates the smoker.- Watchtower recreates containers from the running container's config, not from the
compose file. Any change to
smoker.docker-compose.yml(mounts, devices, env, ports, healthchecks, or the watchtower flags themselves) requires dispatching the Device Deploy workflow.
Watchtower settings can be seen in the smoker.docker-compose.yml file; it is scoped to the
three application containers so it never restarts itself or portainer_agent.
See Physical Smoker Device for the deploy inputs, verification steps and rollback ladder.
Cloud Environment
Containers for the cloud are deployed via GitHub Action workflows.
Network Management
Tailscale Configuration
Using Tailscale to manage the network, providing a private internal network for all devices.
Tailscale creates the SSL cert and key and also serves the sites. The Tailscale funnel feature is used to expose the frontend and backend to the public web for the cloud app:
- Frontend: https://smokecloud.tail74646.ts.net
- Backend: https://smokecloud.tail74646.ts.net:8443
Verifying Tailscale Setup
Use the command tailscale funnel status - it should result in this output if correctly set up:
ubuntu@ubuntu:/etc/nginx/sites-available$ sudo tailscale funnel status
# Funnel on:
# - https://smokecloud.tail74646.ts.net
# - https://smokecloud.tail74646.ts.net:8443
https://smokecloud.tail74646.ts.net (Funnel on)
|-- / proxy http://127.0.0.1:80
https://smokecloud.tail74646.ts.net:8443 (Funnel on)
|-- / proxy http://127.0.0.1:3001
Setting Up Tailscale Funnel
To configure services for external access:
- Set up serve:
tailscale serve http:<port> / <local_port> - Enable funnel:
tailscale funnel <port> on
Repeat for each service you want accessible outside the network.
Deployment Workflow Notes
For the deploy workflow, the process requires:
1. Stop the Tailscale service
2. Run docker compose up
3. Start Tailscale service again
This is necessary because Tailscale holds onto the ports needed, so it must be stopped first to allow containers to bind to the ports, then restarted.
Tailscale Documentation Links
Container Monitoring
Portainer Setup
Using Portainer to host the container monitoring dashboard.
Cloud Pi Installation
To install Portainer on the cloud pi, run the following Docker command:
docker run -d -p 10000:9000 --name portainer --restart always \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce
Once installed, connect to it via smokerCloudIp:10000 (using port 10000 because it was the last available funnel port in Tailscale).
Smoker Pi Setup
To set up the smoker pi, follow the Portainer Agent Environment instructions to configure a Portainer agent environment.
Note: Portainer is not included in the deployment process as it operates as a separate entity from the smoker app. Additionally, resetting the container clears all settings.
Docker Commands Reference
Smoker App Commands
Build and Push Test Smoker Image
Prerequisites: Run npm run build for smoker first
# Build for ARM/v7 platform
docker build -f apps/smoker/Dockerfile --platform linux/arm/v7 \
-t benjr70/smart-smoker-smoker:smokerTest .
# Push to Docker Hub
docker push benjr70/smart-smoker-smoker:smokerTest
Pull and Run Smoker Image on Pi
# Pull latest image
docker pull benjr70/smart-smoker-smoker:smokerTest
# Run container
docker run -p 8080:8080 benjr70/smart-smoker-smoker:smokerTest
Device Service Commands
Build and Push Test Device Service Image
# Build for ARM/v7 platform
docker build -f apps/device-service/Dockerfile --platform linux/arm/v7 \
-t benjr70/smart-smoker-device-service:device-serviceTest .
# Push to Docker Hub
docker push benjr70/smart-smoker-device-service:device-serviceTest
Pull and Run Device Service on Pi
# Pull latest image
docker pull benjr70/smart-smoker-device-service:device-serviceTest
# Run container with USB device access
docker run --privileged --device=/dev/ttyUSB0 -p 3000:3000 \
benjr70/smart-smoker-device-service:device-serviceTest
Architecture Overview
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Development │ │ Docker Hub │ │ Production │
│ │ │ │ │ │
│ • Build Images │───▶│ • Store Images │───▶│ • Watchtower │
│ • Push Updates │ │ • Version Tags │ │ • Auto Deploy │
│ • Test Locally │ │ • Multi-arch │ │ • Health Check │
└─────────────────┘ └──────────────────┘ └─────────────────┘
│ │ │
│ ┌────────▼───────┐ │
│ │ Tailscale │ │
└──────────────│ • Private Net │◀──────────────┘
│ • SSL/HTTPS │
│ • Public Funnel│
└────────────────┘