ci-actions/deploy-nix-site/action.yaml
Christopher Mühl a8e0e936fc
Fix binary cache secret key handling
Write NIX_SIGNING_KEY to temp file since --secret-key expects a path.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 15:37:49 +01:00

186 lines
6.2 KiB
YAML

name: Deploy Nix Site
description: Deploy static site built with Nix flake to S3 and Nomad
inputs:
site-name:
description: 'Site identifier (used as service name in Nomad)'
required: true
traefik-rule:
description: 'Traefik routing rule (e.g., Host(`example.com`) or Host(`example.com`) || Host(`www.example.com`))'
required: true
flake-output:
description: 'Nix flake output to build (e.g., .#packages.x86_64-linux.default or .#)'
required: false
default: '.#'
s3-endpoint:
description: 'S3 endpoint'
required: false
default: 'https://s3.toph.so'
runs:
using: composite
steps:
- name: Install tools
shell: bash
run: |
# Install AWS CLI
nix profile install nixpkgs#awscli2
# Set Nomad address
echo "NOMAD_ADDR=http://alvin:4646" >> $GITHUB_ENV
- name: Build site with Nix
shell: bash
run: |
# Configure S3 as substituter to pull cached dependencies
export AWS_ACCESS_KEY_ID="${{ env.S3_ACCESS_KEY }}"
export AWS_SECRET_ACCESS_KEY="${{ env.S3_SECRET_KEY }}"
# Build with S3 cache as substituter (fetches cached deps)
nix build ${{ inputs.flake-output }} \
--print-build-logs \
--option substituters "https://cache.nixos.org s3://nix-cache?endpoint=${{ inputs.s3-endpoint }}&scheme=https" \
--option trusted-public-keys "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= $(cat /tmp/cache-pub-key.pem 2>/dev/null || echo '')"
# Get the store path
STORE_PATH=$(readlink -f result)
STORE_HASH=$(basename "$STORE_PATH")
echo "STORE_PATH=$STORE_PATH" >> $GITHUB_ENV
echo "STORE_HASH=$STORE_HASH" >> $GITHUB_ENV
echo "📦 Built: $STORE_PATH"
- name: Push to binary cache
shell: bash
run: |
# Configure S3 binary cache
export AWS_ACCESS_KEY_ID="${{ env.S3_ACCESS_KEY }}"
export AWS_SECRET_ACCESS_KEY="${{ env.S3_SECRET_KEY }}"
# Write signing key to temporary file
echo "${{ env.NIX_SIGNING_KEY }}" > /tmp/nix-signing-key.pem
chmod 600 /tmp/nix-signing-key.pem
# Push entire closure (derivation + all dependencies) to cache
nix copy \
--to "s3://nix-cache?endpoint=${{ inputs.s3-endpoint }}&scheme=https&secret-key=/tmp/nix-signing-key.pem" \
--derivation \
"$STORE_PATH"
# Clean up key file
rm -f /tmp/nix-signing-key.pem
echo "✅ Pushed to binary cache: $STORE_HASH (with all dependencies)"
- name: Deploy via Nomad
shell: bash
run: |
# Get S3 credentials for the fetch task
S3_ACCESS_KEY="${{ env.S3_ACCESS_KEY }}"
S3_SECRET_KEY="${{ env.S3_SECRET_KEY }}"
cat > /tmp/deploy-${{ inputs.site-name }}.nomad.json <<NOMAD_EOF
{
"Job": {
"ID": "${{ inputs.site-name }}",
"Name": "${{ inputs.site-name }}",
"Type": "service",
"Datacenters": ["contabo"],
"Constraints": [{
"LTarget": "\${node.unique.name}",
"RTarget": "alvin",
"Operand": "="
}],
"TaskGroups": [{
"Name": "web",
"Count": 1,
"Networks": [{
"Mode": "bridge",
"DynamicPorts": [{
"Label": "http",
"To": 8080
}]
}],
"Services": [{
"Name": "${{ inputs.site-name }}",
"PortLabel": "http",
"Provider": "nomad",
"Tags": [
"traefik.enable=true",
"traefik.http.routers.${{ inputs.site-name }}.rule=${{ inputs.traefik-rule }}",
"traefik.http.routers.${{ inputs.site-name }}.entrypoints=websecure",
"traefik.http.routers.${{ inputs.site-name }}.tls.certresolver=letsencrypt"
]
}],
"Volumes": [{
"Name": "site-data",
"Type": "host",
"Source": "site-data"
}],
"Tasks": [
{
"Name": "fetch",
"Driver": "docker",
"Lifecycle": {
"Hook": "prestart",
"Sidecar": false
},
"Config": {
"image": "nixos/nix:latest",
"command": "/bin/sh",
"args": [
"-c",
"nix copy --from 's3://nix-cache?endpoint=${{ inputs.s3-endpoint }}&scheme=https' '$STORE_PATH' && cp -r $STORE_PATH/* /alloc/data/"
]
},
"Env": {
"AWS_ACCESS_KEY_ID": "$S3_ACCESS_KEY",
"AWS_SECRET_ACCESS_KEY": "$S3_SECRET_KEY"
},
"VolumeMounts": [{
"Volume": "site-data",
"Destination": "/alloc/data"
}],
"Resources": {
"CPU": 200,
"MemoryMB": 256
}
},
{
"Name": "server",
"Driver": "docker",
"Config": {
"image": "joseluisq/static-web-server:2",
"ports": ["http"]
},
"Env": {
"SERVER_ROOT": "/var/www",
"SERVER_LOG_LEVEL": "info"
},
"VolumeMounts": [{
"Volume": "site-data",
"Destination": "/var/www",
"ReadOnly": true
}],
"Resources": {
"CPU": 100,
"MemoryMB": 64
}
}
]
}]
}
}
NOMAD_EOF
nomad job run /tmp/deploy-${{ inputs.site-name }}.nomad.json
- name: Deployment summary
shell: bash
run: |
echo "✅ Deployed ${{ inputs.site-name }}"
echo "📋 Traefik rule: ${{ inputs.traefik-rule }}"
echo "📦 Store path: $STORE_PATH"