cryodev/docs/deployment/cd.md
steffen 10bb0c8e34 add deploy/create/install apps, fix templates and docs
- Add apps: create (scaffold host from template), deploy (multi-host
  deployment with -n filter), install (NixOS installation from live ISO)
- Register all apps in flake.nix (create, deploy, install, rebuild)
- Add deploy.json config (cryodev-main, SSH port 2299)
- Fix generic-server template: was using Pi hardware/boot config,
  now correct x86_64 with systemd-boot, UEFI, ROOT/BOOT/SWAP labels
- Fix template networking.nix: use HOSTNAME placeholder instead of
  hardcoded cryodev-pi (both templates)
- Fix headplane upstream pnpm-deps hash mismatch via overlay
- Fix all docs: replace root@ with user@, --ssh-option with
  NIX_SSHOPTS, add deploy app references, update first-install guide
  to use create app and document service deactivation steps
2026-03-14 12:08:30 +01:00

3.5 KiB

Continuous Deployment

The cryodev infrastructure uses two deployment strategies optimized for different host types.

Overview

Host Strategy Tool Trigger
cryodev-main Push-based deploy-rs Git push via Forgejo Actions
cryodev-pi Pull-based Comin Periodic polling

Push-based Deployment (cryodev-main)

How It Works

  1. Developer pushes to main branch
  2. Forgejo Actions workflow triggers
  3. deploy-rs connects via SSH and deploys

Setup

1. Generate Deploy Key

ssh-keygen -t ed25519 -f deploy_key -C "forgejo-actions"

2. Add Public Key to Server

On cryodev-main:

echo "PUBLIC_KEY_CONTENT" >> /root/.ssh/authorized_keys

3. Add Private Key to Forgejo

  1. Go to Repository Settings > Secrets
  2. Add secret named DEPLOY_SSH_KEY
  3. Paste the private key content

4. Workflow Configuration

.forgejo/workflows/deploy.yaml:

name: Deploy
on:
  push:
    branches: [main]

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v24
      - run: nix flake check

  deploy:
    needs: check
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: cachix/install-nix-action@v24
      
      - name: Setup SSH
        env:
          SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
        run: |
          mkdir -p ~/.ssh
          echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh-keyscan cryodev-main >> ~/.ssh/known_hosts
          
      - name: Deploy
        run: nix run github:serokell/deploy-rs -- .#cryodev-main

Rollback

deploy-rs automatically rolls back if the new configuration fails health checks.

Manual rollback:

# List generations
sudo nix-env -p /nix/var/nix/profiles/system --list-generations

# Rollback to previous
sudo nixos-rebuild switch --rollback

Pull-based Deployment (cryodev-pi)

How It Works

  1. Comin periodically polls the Git repository
  2. On changes, it builds and activates the new configuration
  3. Works through NAT without incoming connections

Configuration

# hosts/cryodev-pi/services/comin.nix
{
  services.comin = {
    enable = true;
    remotes = [{
      name = "origin";
      url = "https://git.cryodev.xyz/steffen/cryodev-server.git";
      branches.main.name = "main";
    }];
  };
}

Monitoring

Check Comin status:

sudo systemctl status comin
sudo journalctl -u comin -f

Force immediate update:

sudo systemctl restart comin

Troubleshooting

If Comin fails to build:

# Check logs
sudo journalctl -u comin --since "1 hour ago"

# Manual build test
cd /var/lib/comin/repo
nix build .#nixosConfigurations.cryodev-pi.config.system.build.toplevel

Manual Deployment

For hosts not using automated deployment:

# Build locally
nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel

# Deploy with nixos-rebuild
NIX_SSHOPTS="-p 2299" nixos-rebuild switch --flake .#<hostname> \
  --target-host <user>@<hostname> --use-remote-sudo

# Or using deploy-rs
nix run github:serokell/deploy-rs -- .#<hostname>

Testing Changes

Before pushing, always verify:

# Check flake validity
nix flake check

# Build configuration (dry-run)
nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel --dry-run

# Full build
nix build .#nixosConfigurations.<hostname>.config.system.build.toplevel