Nomad Deployment Examples
Copy-and-paste examples for pfy nomad: single deploys, stack deploys, per-environment scripts, CI pipelines, and rollbacks. Every example renders the job from the deployment spec stored in the Manager and targets it with --env <alias>, a project.yaml alias managed by pfy env. Outputs shown are abridged.
Table of Contents
- Basic Examples
- Version Management Integration
- Stack Deployments
- Environment-Specific Deployments
- CI/CD Pipeline Examples
- Rollback Scenarios
Basic Examples
Deploy with Explicit Tag
# Deploy the prod environment's job with image tag v1.2.3
pfy nomad deploy --env prod --tag v1.2.3 --yesOutput:
Rendered myapp job to nomad/myapp.nomad.hcl (spec 3f9a2c…)
Deploying spec 9c1d0e… → 3f9a2c…
✓ Rendered job is valid
Running 'nomad job run nomad/myapp.nomad.hcl'...
✓ Job deployed successfullyThe Deploying spec line shows the spec hash stamped on the running job and the new one. It reads Re-deploying spec … (no spec change since last apply) when only the image tag changed, and just Deploying spec … when the job is not running yet or Nomad could not be asked.
Render Without Deploying
# Write the rendered job to the committed artifact path (ci.nomad_file)
pfy nomad render --env prod --tag v1.2.3
# Or print it to stdout
pfy nomad render --env prod --tag v1.2.3 --out -Preview the Rendered Job
# Print the render without writing, validating, or deploying
pfy nomad deploy --env prod --tag v1.2.3 --dry-runAdopt a Hand-Written Job File
# One-time migration: extract the spec from an existing job file
pfy nomad adopt nomad/legacy/manager.nomad --env prod --dry-run # preview
pfy nomad adopt nomad/legacy/manager.nomad --env prod # write the specVersion Management Integration
Bump and Deploy
# Bump version in project.yaml
pfy version bump --part minor
# Deploy using the bumped version as the image tag
pfy nomad deploy --env prod --use-project-version --yesOutput:
Version updated: 1.2.3 → 1.3.0
Configuration saved to project.yaml
Rendered myapp job to nomad/myapp.nomad.hcl (spec 3f9a2c…)
Re-deploying spec 3f9a2c… (no spec change since last apply)
✓ Rendered job is valid
Running 'nomad job run nomad/myapp.nomad.hcl'...
✓ Job deployed successfullySet Specific Version and Deploy to Every Environment
# Set version to 2.0.0
pfy version set --version 2.0.0
# Deploy each environment alias with the new version
for env in dev staging prod; do
pfy nomad deploy --env $env --use-project-version --yes
doneStack Deployments
An application is a stack: managed data stores (postgres/redis), their backup jobs, and the services that consume them. --stack applies all of it in dependency order, waiting for each stage to become healthy.
Deploy the Full Stack
pfy nomad deploy --stack \
--env prod \
--app myapp --project my-saas \
--tag v1.3.0 \
--install install.yaml \
--yesOutput (abridged):
Generated a credential for main at <nomad var path>
Rendered myapp--main (data store) to deploy/myapp--main.nomad.hcl
Running 'nomad job run deploy/myapp--main.nomad.hcl'...
Waiting for myapp--main (data store) to become healthy...
✓ myapp--main is healthy
Rendered myapp (service, with prestart migration) to deploy/myapp.nomad.hcl
Running 'nomad job run deploy/myapp.nomad.hcl'...
✓ Stack applied (3 jobs)Only the Data Stores
pfy nomad deploy --stack --env prod --app myapp --project my-saas --only-data --yesOne Service of the Stack
pfy nomad deploy --stack --env prod --app myapp --project my-saas --service api --yesStaged Deployment with Validation
#!/bin/bash
# deploy-with-validation.sh
ENVS=("dev" "staging" "prod")
for env in "${ENVS[@]}"; do
echo "Planning $env..."
pfy nomad deploy --env $env --use-project-version --plan-only
read -p "Deploy $env? (y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
pfy nomad deploy --env $env --use-project-version --yes
fi
doneEnvironment-Specific Deployments
Each environment is one project.yaml alias resolving to its own deployment spec; there is no per-environment job file to maintain.
Development Environment
# Deploy latest development build
pfy nomad deploy --env dev --tag dev-latest --yes
# Or use the branch name
BRANCH=$(git rev-parse --abbrev-ref HEAD)
pfy nomad deploy --env dev --tag dev-$BRANCH --yesStaging Environment
# Deploy a specific version to staging
pfy nomad deploy --env staging --tag v1.3.0 --yes
# Or use the project version
pfy nomad deploy --env staging --use-project-version --yesProduction Environment
# Always plan first in production
pfy nomad deploy --env prod --tag v1.3.0 --plan-only
# Review output carefully, then deploy
pfy nomad deploy --env prod --tag v1.3.0 --yesDedicated Tenants
# The shared deployment
pfy nomad deploy --env prod --tag v1.3.0 --yes
# A tenant's dedicated deployment (job name myapp--acme, server-derived)
pfy nomad deploy --env prod --tenant acme --tag v1.3.0 --yesEnvironment Deployment Script
#!/bin/bash
# deploy-env.sh <environment> <version>
ENV=$1
VERSION=$2
if [ -z "$ENV" ] || [ -z "$VERSION" ]; then
echo "Usage: $0 <dev|staging|prod> <version>"
exit 1
fi
if [ "$ENV" = "prod" ]; then
echo "Planning production deployment..."
pfy nomad deploy --env $ENV --tag $VERSION --plan-only
read -p "Proceed with production deployment? (yes/no) " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "Deployment cancelled"
exit 0
fi
fi
echo "Deploying to $ENV..."
pfy nomad deploy --env $ENV --tag $VERSION --yes
echo "✓ Deployment to $ENV complete"CI/CD Pipeline Examples
GitHub Actions Workflow
name: Deploy to Nomad
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
environment:
description: "Deployment environment"
required: true
default: "staging"
type: choice
options:
- dev
- staging
- prod
env:
NOMAD_ADDR: ${{ secrets.NOMAD_ADDR }}
NOMAD_TOKEN: ${{ secrets.NOMAD_TOKEN }}
PFY_MANAGER_URL: ${{ secrets.PFY_MANAGER_URL }}
PFY_MANAGER_TOKEN: ${{ secrets.PFY_MANAGER_TOKEN }}
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pfy CLI
run: |
PFY_VERSION=$(curl -fsSL https://api.github.com/repos/ProductifyFW/cli/releases/latest | sed -n 's/.*"tag_name": *"v\([^"]*\)".*/\1/p')
curl -fsSLO "https://github.com/ProductifyFW/cli/releases/download/v${PFY_VERSION}/pfy_${PFY_VERSION}_linux_amd64.tar.gz"
curl -fsSLO "https://github.com/ProductifyFW/cli/releases/download/v${PFY_VERSION}/checksums.txt"
grep "pfy_${PFY_VERSION}_linux_amd64.tar.gz" checksums.txt | sha256sum -c -
tar -xzf "pfy_${PFY_VERSION}_linux_amd64.tar.gz" pfy
sudo mv pfy /usr/local/bin/pfy
- name: Extract version
id: version
run: |
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
VERSION=$(pfy version show)
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Deploy to staging
if: github.event.inputs.environment == 'staging' || github.ref_type == 'tag'
run: |
pfy --ci nomad deploy \
--env staging \
--tag v${{ steps.version.outputs.version }} \
--yes
- name: Deploy to production
if: github.event.inputs.environment == 'prod'
run: |
# Plan first
pfy --ci nomad deploy \
--env prod \
--tag v${{ steps.version.outputs.version }} \
--plan-only
# Deploy
pfy --ci nomad deploy \
--env prod \
--tag v${{ steps.version.outputs.version }} \
--yesGitLab CI/CD Pipeline
The jobs also need NOMAD_TOKEN, PFY_MANAGER_URL, and PFY_MANAGER_TOKEN as CI/CD variables, and an image with curl and tar.
stages:
- build
- deploy:dev
- deploy:staging
- deploy:prod
variables:
NOMAD_ADDR: $NOMAD_SERVER_URL
PFY_VERSION: "2.0.0" # pin the pfy release to install
before_script:
- curl -fsSLO "https://github.com/ProductifyFW/cli/releases/download/v${PFY_VERSION}/pfy_${PFY_VERSION}_linux_amd64.tar.gz"
- tar -xzf "pfy_${PFY_VERSION}_linux_amd64.tar.gz" pfy
- mv pfy /usr/local/bin/pfy
# Deploy to development on every commit
deploy:dev:
stage: deploy:dev
script:
- VERSION=$(git rev-parse --short HEAD)
- pfy --ci nomad deploy --env dev --tag dev-$VERSION --yes
environment:
name: development
only:
- main
# Deploy to staging on tags
deploy:staging:
stage: deploy:staging
script:
- VERSION=${CI_COMMIT_TAG#v}
- pfy --ci nomad deploy --env staging --tag v$VERSION --yes
environment:
name: staging
only:
- tags
# Deploy to production manually
deploy:prod:
stage: deploy:prod
script:
- VERSION=${CI_COMMIT_TAG#v}
- pfy --ci nomad deploy --env prod --tag v$VERSION --plan-only
- pfy --ci nomad deploy --env prod --tag v$VERSION --yes
environment:
name: production
only:
- tags
when: manualRollback Scenarios
Quick Rollback
# Rollback to the previous image tag
pfy nomad deploy --env prod --tag v1.2.3 --yesRollback with Git
# Find previous version
git log --oneline project.yaml | head -5
# Checkout previous version
git show HEAD~1:project.yaml | grep version
# Rollback
pfy nomad deploy --env prod --tag v1.2.3 --yesRolling back the tag does not roll back spec changes; check pfy deploy diff --env prod and pfy deployment get --env prod when the regression is not image-related.
Automated Rollback Script
#!/bin/bash
# rollback.sh <environment> <previous-version>
ENV=$1
PREV_VERSION=$2
if [ -z "$ENV" ] || [ -z "$PREV_VERSION" ]; then
echo "Usage: $0 <environment> <version>"
exit 1
fi
echo "Rolling back $ENV to $PREV_VERSION"
# Plan the rollback
pfy nomad deploy --env $ENV --tag $PREV_VERSION --plan-only
read -p "Proceed with rollback? (yes/no) " CONFIRM
if [ "$CONFIRM" != "yes" ]; then
echo "Rollback cancelled"
exit 0
fi
# Execute rollback
pfy nomad deploy --env $ENV --tag $PREV_VERSION --yes
echo "✓ Rollback complete"See Also
- Nomad Commands Reference
- Nomad Deployment Guide
- deployment - Deployment-spec scripting
- Version Management