cryodev/docs/getting-started/new-client.md
steffen a0da5be8fc translate all docs to English
Translate 8 documentation files from German to English:
- docs/index.md (complete)
- docs/getting-started/first-install.md (complete)
- docs/getting-started/new-client.md (complete)
- docs/getting-started/reinstall.md (complete)
- docs/getting-started/sd-image.md (complete)
- docs/deployment/dns.md (PTR, Hetzner, checklist sections)
- docs/services/tailscale.md (code comments)
- docs/services/forgejo.md (placeholder names)
2026-03-14 15:31:50 +01:00

5.4 KiB

Adding a New Raspberry Pi Client

This guide describes how to add a new Raspberry Pi client to the infrastructure.

Overview: The Process

1. Create configuration         ──► Copy template, customize
         │
         ▼
2. Add to image pipeline        ──► Extend workflow matrix
         │
         ▼
3. Push to main                 ──► Forgejo automatically builds SD image
         │
         ▼
4. Flash image & boot           ──► Write SD card, start Pi
         │
         ▼
5. Configure SOPS               ──► Retrieve age key, create secrets
         │
         ▼
6. Final deployment             ──► Activate Tailscale etc.

Prerequisites

  • SSH access to cryodev-main (for Tailscale auth key)
  • Development machine with repository access
  • SD card (at least 8 GB)

Step 1: Generate Tailscale Auth Key

On cryodev-main (via SSH):

# Determine user ID
sudo headscale users list
# Create preauth key (use user ID of "default")
sudo headscale preauthkeys create --expiration 99y --reusable --user <ID>

Take note of the output! (e.g. tskey-preauth-abc123...)


Step 2: Create Host Configuration

2.1 Copy Template

cp -r templates/raspberry-pi hosts/neuer-pi

2.2 Set Hostname

hosts/neuer-pi/networking.nix:

{
  networking.hostName = "neuer-pi";
}

2.3 Register in flake.nix

nixosConfigurations = {
  # ... existing hosts ...
  
  neuer-pi = mkNixosConfiguration "aarch64-linux" [ ./hosts/neuer-pi ];
};

2.4 Add to constants.nix

{
  hosts = {
    # ... existing hosts ...
    
    neuer-pi = {
      ip = "100.64.0.X";  # Assigned by Headscale
    };
  };
}

2.5 Create Placeholder secrets.yaml

touch hosts/neuer-pi/secrets.yaml

2.6 Temporarily Disable SOPS

In hosts/neuer-pi/default.nix, comment out the sops.secrets.* references so the image can be built without secrets.


Step 3: Add to Image Pipeline

Edit .forgejo/workflows/build-pi-image.yml:

jobs:
  build-pi-images:
    strategy:
      matrix:
        # Add new host here:
        host: [cryodev-pi, neuer-pi]

Step 4: Push and Build Image

git add .
git commit -m "Add neuer-pi host configuration"
git push

The Forgejo workflow will now automatically build an SD image for neuer-pi.

Wait until the workflow completes (30-60 minutes). Check the status at: https://git.cryodev.xyz/steffen/cryodev-server/actions


Step 5: Flash Image

5.1 Download Image

After a successful build, find the image under Releases:

wget https://git.cryodev.xyz/steffen/cryodev-server/releases/latest/download/neuer-pi-sd-image.img.zst

5.2 Decompress

zstd -d neuer-pi-sd-image.img.zst -o neuer-pi.img

5.3 Write to SD Card

Warning: Replace /dev/sdX with the correct device!

lsblk  # Identify the correct device
sudo dd if=neuer-pi.img of=/dev/sdX bs=4M conv=fsync status=progress

5.4 Boot

  1. Insert the SD card into the Raspberry Pi
  2. Connect Ethernet
  3. Connect power
  4. Wait until booted (approximately 2 minutes)

Step 6: Configure SOPS

6.1 Find IP Address

The Pi should receive an IP address via DHCP. Check your router or scan the network:

nmap -sn 192.168.1.0/24 | grep -B2 "Raspberry"

6.2 Connect via SSH

ssh steffen@<IP>  # or the configured user

For the default password, see hosts/neuer-pi/users.nix.

6.3 Determine Age Key

On the Pi:

nix-shell -p ssh-to-age --run 'cat /etc/ssh/ssh_host_ed25519_key.pub | ssh-to-age'

Take note of the output! (e.g. age1xyz...)

6.4 Update .sops.yaml

On the development machine:

keys:
  - &steffen_key age1e8p35795htf7twrejyugpzw0qja2v33awcw76y4gp6acnxnkzq0s935t4t  # steffen (local)
  - &neuer_pi_key age1xyz...  # The new key

creation_rules:
  # ... existing rules ...

  - path_regex: hosts/neuer-pi/secrets.yaml$
    key_groups:
      - age:
          - *steffen_key
          - *neuer_pi_key

6.5 Create Secrets

sops hosts/neuer-pi/secrets.yaml

Contents:

tailscale:
  auth-key: "tskey-preauth-abc123..."  # Key from Step 1

netdata:
  stream:
    child-uuid: "..."  # uuidgen

6.6 Activate SOPS References

Re-enable the sops.secrets.* references that were commented out in Step 2.6.


Step 7: Final Deployment

git add .
git commit -m "Configure SOPS secrets for neuer-pi"
git push

Since Comin is running on the Pi, it will automatically pull the new configuration.

Alternatively, deploy manually:

NIX_SSHOPTS="-p 2299" nixos-rebuild switch --flake .#neuer-pi \
  --target-host <user>@<IP> --sudo --ask-sudo-password

Step 8: Verify

Tailscale Connection

# On the Pi
tailscale status

# On cryodev-main
sudo headscale nodes list

Netdata Streaming

Check whether the new client appears in the Netdata dashboard: https://netdata.cryodev.xyz


Checklist

  • Tailscale auth key generated on cryodev-main
  • Host configuration created (template, flake.nix, constants.nix)
  • Host added to workflow matrix
  • Pushed and waited for image build
  • SD card flashed and Pi booted
  • Age key determined and added to .sops.yaml
  • secrets.yaml created (Tailscale key, Netdata UUID)
  • SOPS references activated and deployed
  • Tailscale connection working
  • Netdata streaming working