Rekey secrets for green generation nodes
This commit is contained in:
parent
43e03343b9
commit
d7317fbb58
48 changed files with 1097 additions and 215 deletions
|
|
@ -138,5 +138,5 @@ Each module has detailed documentation:
|
|||
- **Colmena**: NixOS deployment tool
|
||||
- **Nomad**: Workload orchestration
|
||||
- **Tailscale**: Zero-config VPN
|
||||
- **agenix**: Age-based secrets management
|
||||
- **agenix-rekey**: Automated age-based secrets management
|
||||
|
||||
|
|
|
|||
235
SECRETS_MANAGEMENT.md
Normal file
235
SECRETS_MANAGEMENT.md
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
# Secrets Management with agenix-rekey
|
||||
|
||||
## Overview
|
||||
|
||||
NCM uses [agenix-rekey](https://github.com/oddlama/agenix-rekey) for automated secrets management. This eliminates the need for manually maintaining per-host `secrets.nix` files and automatically handles re-encryption when host keys change.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Central Secret Storage
|
||||
|
||||
```
|
||||
secrets/
|
||||
├── master/ # Source secrets (encrypted with master key)
|
||||
│ ├── tailscale_auth_key
|
||||
│ └── linode_cli_pat
|
||||
└── rekeyed/ # Per-host encrypted secrets (auto-generated)
|
||||
├── ncm-0/
|
||||
│ ├── <hash>-tailscale_auth_key.age
|
||||
│ └── <hash>-linode_cli_pat.age
|
||||
├── ncm-1/
|
||||
│ └── ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Master Key
|
||||
|
||||
- Location: `~/.ssh/id_rsa_agenix`
|
||||
- Purpose: Decrypt master secrets and re-encrypt for hosts
|
||||
- Never deployed to servers
|
||||
|
||||
### Host Keys
|
||||
|
||||
Each host has a unique age public key derived from its SSH ed25519 host key:
|
||||
|
||||
```nix
|
||||
# In operate/hosts/ncm-X/default.nix
|
||||
age.rekey.hostPubkey = "age1...";
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Master secrets** are encrypted with the master key and stored in `secrets/master/`
|
||||
2. **agenix-rekey** reads each host's `hostPubkey` from NixOS configurations
|
||||
3. For each host, it:
|
||||
- Decrypts the master secret using the master key
|
||||
- Re-encrypts it with the host's public key
|
||||
- Stores the result in `secrets/rekeyed/<hostname>/`
|
||||
4. During deployment, NixOS uses the host's private key to decrypt its secrets
|
||||
|
||||
## Common Operations
|
||||
|
||||
### Edit a Secret
|
||||
|
||||
```bash
|
||||
# Edit the master copy
|
||||
cd secrets/master/
|
||||
agenix -e tailscale_auth_key -i ~/.ssh/id_rsa_agenix
|
||||
|
||||
# Rekey for all hosts
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey
|
||||
|
||||
# Commit the changes
|
||||
git add secrets/
|
||||
git commit -m "Update tailscale_auth_key"
|
||||
```
|
||||
|
||||
### Add a New Secret
|
||||
|
||||
```bash
|
||||
# Create the master secret
|
||||
cd secrets/master/
|
||||
echo "secret-value" | agenix -e new_secret -i ~/.ssh/id_rsa_agenix
|
||||
|
||||
# Add to git (required for agenix-rekey to see it)
|
||||
git add new_secret
|
||||
|
||||
# Add to host configurations
|
||||
# Edit operate/hosts/*/default.nix:
|
||||
age.secrets.new_secret = {
|
||||
rekeyFile = ../../../secrets/master/new_secret;
|
||||
};
|
||||
|
||||
# Rekey for all hosts
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey
|
||||
|
||||
# Commit everything
|
||||
git add secrets/ operate/hosts/
|
||||
git commit -m "Add new_secret"
|
||||
```
|
||||
|
||||
### Handle Host Key Changes
|
||||
|
||||
When a host is recreated and gets a new SSH host key:
|
||||
|
||||
```bash
|
||||
# 1. Scan the new SSH key
|
||||
ssh-keyscan <host-ip> | grep ssh-ed25519
|
||||
|
||||
# 2. Convert to age format
|
||||
echo "ssh-ed25519 AAAA..." | nix-shell -p ssh-to-age --run "ssh-to-age"
|
||||
|
||||
# 3. Update the host configuration
|
||||
# Edit operate/hosts/<hostname>/default.nix:
|
||||
age.rekey.hostPubkey = "age1..."; # New key
|
||||
|
||||
# 4. Rekey secrets
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey
|
||||
|
||||
# 5. Commit and deploy
|
||||
git add secrets/rekeyed/ operate/hosts/<hostname>/default.nix
|
||||
git commit -m "Update <hostname> host key"
|
||||
colmena apply --on <hostname> --impure
|
||||
```
|
||||
|
||||
The upgrade script (`nomad-1.11-upgrade.sh`) automates this process.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Host Configuration
|
||||
|
||||
Each host needs:
|
||||
|
||||
```nix
|
||||
{
|
||||
# Shared configuration (from rekey.nix)
|
||||
imports = [
|
||||
../rekey.nix # Provides masterIdentities
|
||||
# ...
|
||||
];
|
||||
|
||||
# Host-specific configuration
|
||||
age.rekey.storageMode = "local";
|
||||
age.rekey.hostPubkey = "age1..."; # From ssh-to-age
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-X;
|
||||
|
||||
# Secrets this host needs
|
||||
age.secrets.tailscale_auth_key = {
|
||||
rekeyFile = ../../../secrets/master/tailscale_auth_key;
|
||||
};
|
||||
|
||||
age.secrets.linode_cli_pat = {
|
||||
rekeyFile = ../../../secrets/master/linode_cli_pat;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Shared Configuration
|
||||
|
||||
`operate/hosts/rekey.nix` provides the master identity:
|
||||
|
||||
```nix
|
||||
{
|
||||
age.rekey.masterIdentities = [
|
||||
{
|
||||
identity = "/home/adriano/.ssh/id_rsa_agenix";
|
||||
}
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
### Flake Configuration
|
||||
|
||||
`flake.nix` configures agenix-rekey:
|
||||
|
||||
```nix
|
||||
{
|
||||
outputs = { self, ... }: {
|
||||
# nixosConfigurations required for agenix-rekey to discover hosts
|
||||
nixosConfigurations = lib.genAttrs hostNames mkHost;
|
||||
|
||||
# agenix-rekey integration
|
||||
agenix-rekey = inputs.agenix-rekey.configure {
|
||||
userFlake = self;
|
||||
nixosConfigurations = self.nixosConfigurations;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Advantages over Manual agenix
|
||||
|
||||
1. **No secrets.nix maintenance**: Don't need to manually list recipient public keys
|
||||
2. **Automatic re-encryption**: When host keys change, just update `hostPubkey` and rekey
|
||||
3. **Git-friendly**: Rekeyed secrets are deterministic (same inputs = same outputs)
|
||||
4. **Type-safe**: NixOS validates secret paths at build time
|
||||
5. **Centralized**: All master secrets in one place
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "rekeyFile doesn't exist" error
|
||||
|
||||
Secrets must be committed to git for agenix-rekey to see them:
|
||||
|
||||
```bash
|
||||
git add secrets/master/<secret-name>
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey
|
||||
```
|
||||
|
||||
### "storageMode not set" error
|
||||
|
||||
Each host needs `age.rekey.storageMode = "local";` in its configuration.
|
||||
|
||||
### Rekeyed secrets not updating
|
||||
|
||||
Force a rekey:
|
||||
|
||||
```bash
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey -- --force
|
||||
git add secrets/rekeyed/
|
||||
```
|
||||
|
||||
### Host can't decrypt secret
|
||||
|
||||
Check the hostPubkey matches the actual host:
|
||||
|
||||
```bash
|
||||
# On the host:
|
||||
ssh-keyscan localhost | grep ssh-ed25519 | ssh-to-age
|
||||
|
||||
# Compare with:
|
||||
nix eval .#nixosConfigurations.<hostname>.config.age.rekey.hostPubkey
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Master key**: Keep `~/.ssh/id_rsa_agenix` secure; it can decrypt all secrets
|
||||
- **Rekeyed secrets**: Safe to commit to git; each is encrypted for only one host
|
||||
- **Public repo**: If your repo is public and a host private key leaks, an attacker could decrypt that host's secrets from git history
|
||||
- **CI/CD**: Can build systems without the master key (rekeyed secrets are already encrypted)
|
||||
|
||||
## References
|
||||
|
||||
- [agenix-rekey GitHub](https://github.com/oddlama/agenix-rekey)
|
||||
- [agenix GitHub](https://github.com/ryantm/agenix)
|
||||
- [age encryption](https://age-encryption.org/)
|
||||
370
UPGRADE_SCRIPT_USAGE.md
Normal file
370
UPGRADE_SCRIPT_USAGE.md
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
# Nomad 1.11 Upgrade Script Usage (AI-Executable)
|
||||
|
||||
## Overview
|
||||
|
||||
The `nomad-1.11-upgrade.sh` script is designed to be executed by an AI agent with full automation and resume capability. All file edits are performed programmatically - no manual intervention required.
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. State Tracking
|
||||
Progress is tracked in `.upgrade-state.json`:
|
||||
```json
|
||||
{
|
||||
"started_at": "2026-03-29T10:30:00Z",
|
||||
"phases": {
|
||||
"1": {"status": "completed", "completed_at": "2026-03-29T10:35:00Z"},
|
||||
"2": {"status": "in_progress"},
|
||||
...
|
||||
},
|
||||
"current_phase": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Resume Capability
|
||||
Stop at any point and resume later:
|
||||
```bash
|
||||
# Script stops/crashes during Phase 3
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
# Automatically resumes from Phase 3
|
||||
```
|
||||
|
||||
### 3. Automated File Editing
|
||||
All configuration changes are automated:
|
||||
- Template updates
|
||||
- Host config updates
|
||||
- Terraform outputs
|
||||
- Flake.nix updates
|
||||
|
||||
No human intervention needed.
|
||||
|
||||
## Usage
|
||||
|
||||
### Initial Run (Full Automation)
|
||||
```bash
|
||||
# Dry run first (recommended)
|
||||
./nomad-1.11-upgrade.sh --dry-run
|
||||
|
||||
# Then live execution
|
||||
./nomad-1.11-upgrade.sh
|
||||
```
|
||||
|
||||
### Resume After Interruption
|
||||
```bash
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
```
|
||||
|
||||
### Start from Specific Phase
|
||||
```bash
|
||||
# Start from Phase 3 (skip 1 and 2)
|
||||
./nomad-1.11-upgrade.sh --phase 3
|
||||
```
|
||||
|
||||
## Command Line Options
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `--dry-run` | Show what would be executed without making changes |
|
||||
| `--resume` | Resume from last completed phase (reads state file) |
|
||||
| `--phase N` | Start from phase N (overrides resume) |
|
||||
| `--help` | Show help text |
|
||||
|
||||
## Phases & State
|
||||
|
||||
### Phase 1: Pre-Upgrade Validation
|
||||
**State**: `phases.1.status = "completed"`
|
||||
- Creates backup directory
|
||||
- Documents current cluster state
|
||||
- Validates cluster health
|
||||
- Records current leader
|
||||
|
||||
**Exit Point**: Clean state, safe to stop
|
||||
|
||||
### Phase 2: Upgrade Green Generation
|
||||
**State**: `phases.2.status = "completed"`
|
||||
- Updates templates (automated)
|
||||
- Updates host configs (automated)
|
||||
- Fetches new SSH host keys from green nodes
|
||||
- Converts SSH keys to age format
|
||||
- Updates hostPubkey in host configurations
|
||||
- Runs agenix-rekey to encrypt secrets for new host keys
|
||||
- Deploys via colmena
|
||||
- Monitors upgrade
|
||||
- Transfers leadership if needed
|
||||
|
||||
**Exit Point**: Mixed version cluster (1.9 + 1.11), safe to stop
|
||||
|
||||
### Phase 3: Migrate Workloads
|
||||
**State**: `phases.3.status = "completed"`
|
||||
- Disables scheduling on old nodes
|
||||
- Drains nodes one-by-one
|
||||
- Verifies workload migration
|
||||
|
||||
**Exit Point**: All workloads on green generation, old nodes idle
|
||||
|
||||
### Phase 4: Decommission Old Generation
|
||||
**State**: `phases.4.status = "completed"`
|
||||
- Stops Nomad on old nodes
|
||||
- Removes from Terraform state
|
||||
- Updates Terraform outputs (automated)
|
||||
- Updates DNS records
|
||||
- Destroys Linode instances
|
||||
|
||||
**Exit Point**: Only green generation remains
|
||||
|
||||
### Phase 5: Cleanup & Finalization
|
||||
**State**: `phases.5.status = "completed"`
|
||||
- Archives old configs
|
||||
- Updates flake (automated)
|
||||
- Commits changes
|
||||
- Final verification
|
||||
|
||||
**Exit Point**: Complete, fully cleaned up
|
||||
|
||||
## Resume Behavior
|
||||
|
||||
The script automatically detects what needs to be done:
|
||||
|
||||
```bash
|
||||
# Scenario 1: Phase 1 complete, Phase 2 not started
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
# Starts at Phase 2
|
||||
|
||||
# Scenario 2: Phase 3 in progress (crashed mid-drain)
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
# Starts at Phase 3 (idempotent drain operations)
|
||||
|
||||
# Scenario 3: All phases complete
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
# Shows "All phases already completed!"
|
||||
```
|
||||
|
||||
## Idempotency
|
||||
|
||||
Each phase is designed to be idempotent:
|
||||
|
||||
- **Phase 1**: Re-running captures latest state
|
||||
- **Phase 2**: Re-running checks version, skips if already 1.11
|
||||
- **Phase 3**: Re-running drains checks allocation count first
|
||||
- **Phase 4**: Re-running state removal checks if resource exists
|
||||
- **Phase 5**: Re-running archival checks if already moved
|
||||
|
||||
## Output & Logging
|
||||
|
||||
### Log File
|
||||
```
|
||||
nomad-upgrade-20260329-103000.log
|
||||
```
|
||||
Timestamped, contains full execution history.
|
||||
|
||||
### State File
|
||||
```
|
||||
.upgrade-state.json
|
||||
```
|
||||
Machine-readable progress tracking.
|
||||
|
||||
### Backup Directory
|
||||
```
|
||||
./backups/upgrade-20260329-103000/
|
||||
```
|
||||
Pre-upgrade snapshots for rollback.
|
||||
|
||||
### Log Levels
|
||||
|
||||
- **[INFO]** - General information
|
||||
- **[SUCCESS]** - Successful operations
|
||||
- **[WARNING]** - Warnings (non-fatal)
|
||||
- **[ERROR]** - Errors (may be fatal)
|
||||
- **[PHASE]** - Phase transitions
|
||||
- **[STEP]** - Step within phase
|
||||
- **[STATE]** - State file updates
|
||||
|
||||
## AI Agent Integration
|
||||
|
||||
### Recommended Workflow for AI
|
||||
|
||||
1. **Validate Environment**
|
||||
```bash
|
||||
# Check prerequisites
|
||||
nomad server members
|
||||
nomad node status
|
||||
```
|
||||
|
||||
2. **Run Dry-Run**
|
||||
```bash
|
||||
./nomad-1.11-upgrade.sh --dry-run 2>&1 | tee dry-run.log
|
||||
# Parse output, check for errors
|
||||
```
|
||||
|
||||
3. **Execute with Monitoring**
|
||||
```bash
|
||||
./nomad-1.11-upgrade.sh 2>&1 | tee execution.log
|
||||
# Parse state file periodically
|
||||
# Monitor for errors in log
|
||||
```
|
||||
|
||||
4. **Handle Interruptions**
|
||||
```bash
|
||||
# If script stops/fails
|
||||
cat .upgrade-state.json # Check progress
|
||||
./nomad-1.11-upgrade.sh --resume # Continue
|
||||
```
|
||||
|
||||
5. **Verify Completion**
|
||||
```bash
|
||||
jq '.phases | to_entries | map(select(.value.status != "completed"))' .upgrade-state.json
|
||||
# Should return []
|
||||
```
|
||||
|
||||
### State File Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"started_at": "ISO8601 timestamp",
|
||||
"phases": {
|
||||
"1": {
|
||||
"status": "pending|in_progress|completed|failed",
|
||||
"name": "phase_name",
|
||||
"in_progress_at": "ISO8601 timestamp",
|
||||
"completed_at": "ISO8601 timestamp"
|
||||
}
|
||||
},
|
||||
"current_phase": 1-5,
|
||||
"dry_run": true|false
|
||||
}
|
||||
```
|
||||
|
||||
### Parsing Status
|
||||
|
||||
```bash
|
||||
# Get current phase
|
||||
jq -r '.current_phase' .upgrade-state.json
|
||||
|
||||
# Get phase status
|
||||
jq -r '.phases."3".status' .upgrade-state.json
|
||||
|
||||
# Check if all complete
|
||||
jq -r '.phases | to_entries | all(.value.status == "completed")' .upgrade-state.json
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Script Exits on Error
|
||||
Exit codes:
|
||||
- `0` - Success
|
||||
- `1` - Error in phase execution
|
||||
- Non-zero - Command failure
|
||||
|
||||
### Resume After Error
|
||||
```bash
|
||||
# Review error in log
|
||||
tail -n 100 nomad-upgrade-*.log
|
||||
|
||||
# Check state
|
||||
cat .upgrade-state.json
|
||||
|
||||
# Fix issue (if manual intervention needed)
|
||||
# Then resume
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### State File Corrupted
|
||||
```bash
|
||||
# Reset state
|
||||
rm .upgrade-state.json
|
||||
|
||||
# Start fresh or from specific phase
|
||||
./nomad-1.11-upgrade.sh --phase 1
|
||||
```
|
||||
|
||||
### Phase Stuck
|
||||
```bash
|
||||
# Check what's running
|
||||
nomad node status
|
||||
nomad server members
|
||||
|
||||
# Manually complete operation
|
||||
# Update state file
|
||||
jq '.phases."2".status = "completed"' .upgrade-state.json > .upgrade-state.json.tmp
|
||||
mv .upgrade-state.json.tmp .upgrade-state.json
|
||||
|
||||
# Resume next phase
|
||||
./nomad-1.11-upgrade.sh --resume
|
||||
```
|
||||
|
||||
### Rollback Needed
|
||||
```bash
|
||||
# Restore from backup
|
||||
cp operate/hosts/ncm-{3,4,5}/default.nix.backup operate/hosts/ncm-{3,4,5}/default.nix
|
||||
|
||||
# Redeploy old version
|
||||
colmena apply --on ncm-3,ncm-4,ncm-5 --impure
|
||||
|
||||
# Re-enable old nodes
|
||||
nomad node eligibility -enable <node-id>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Full Automation (AI Agent)
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Pre-flight checks
|
||||
echo "Checking cluster health..."
|
||||
nomad server members | grep -q "alive" || exit 1
|
||||
|
||||
# Dry run
|
||||
echo "Running dry-run..."
|
||||
./nomad-1.11-upgrade.sh --dry-run
|
||||
|
||||
# Execute
|
||||
echo "Starting upgrade..."
|
||||
./nomad-1.11-upgrade.sh
|
||||
|
||||
# Verify
|
||||
echo "Verifying completion..."
|
||||
jq -e '.phases | to_entries | all(.value.status == "completed")' .upgrade-state.json
|
||||
nomad server members
|
||||
nomad node status
|
||||
|
||||
echo "Upgrade complete!"
|
||||
```
|
||||
|
||||
### Phase-by-Phase with Validation
|
||||
```bash
|
||||
#!/bin/bash
|
||||
|
||||
phases=(1 2 3 4 5)
|
||||
|
||||
for phase in "${phases[@]}"; do
|
||||
echo "=== Running Phase $phase ==="
|
||||
|
||||
./nomad-1.11-upgrade.sh --phase $phase
|
||||
|
||||
echo "=== Phase $phase Complete ==="
|
||||
echo "Validating..."
|
||||
|
||||
nomad server members
|
||||
nomad node status
|
||||
|
||||
echo "Press Enter to continue to next phase..."
|
||||
read
|
||||
done
|
||||
```
|
||||
|
||||
## Integration with Claude Code
|
||||
|
||||
When executing this script via Claude Code:
|
||||
|
||||
1. Claude reads the plan
|
||||
2. Claude executes: `./nomad-1.11-upgrade.sh --dry-run`
|
||||
3. Claude reviews dry-run output
|
||||
4. Claude executes: `./nomad-1.11-upgrade.sh`
|
||||
5. Claude monitors `.upgrade-state.json` and logs
|
||||
6. If interrupted, Claude resumes: `./nomad-1.11-upgrade.sh --resume`
|
||||
7. Claude verifies final state
|
||||
|
||||
No manual intervention needed at any point.
|
||||
|
|
@ -6,7 +6,7 @@ This module manages NixOS configurations for cluster nodes using Colmena.
|
|||
|
||||
The operate module:
|
||||
- Defines NixOS system configurations for each cluster node
|
||||
- Manages secrets with agenix
|
||||
- Manages secrets with agenix-rekey (automated re-encryption on host key changes)
|
||||
- Configures Nomad cluster (server + client mode)
|
||||
- Sets up Tailscale VPN
|
||||
- Manages firewall rules and networking
|
||||
|
|
@ -27,11 +27,14 @@ operate/
|
|||
## Host Configuration
|
||||
|
||||
Each host directory contains:
|
||||
- `default.nix` - Main system configuration
|
||||
- `default.nix` - Main system configuration (includes hostPubkey for secret encryption)
|
||||
- `base-system.nix` - Common system settings
|
||||
- `hardware-configuration.nix` - Hardware-specific config
|
||||
- `nomad.nix` - Nomad cluster configuration
|
||||
- `secrets/` - Encrypted secrets (agenix)
|
||||
|
||||
Secrets are managed centrally:
|
||||
- `../../secrets/master/` - Source secrets (encrypted with master key)
|
||||
- `../../secrets/rekeyed/` - Per-host encrypted secrets (auto-generated by agenix-rekey)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -98,13 +101,22 @@ colmena exec --on @all -- tailscale status
|
|||
|
||||
### Manage Secrets
|
||||
|
||||
Secrets are encrypted with agenix. To edit:
|
||||
Secrets are managed centrally with agenix-rekey. To edit a secret:
|
||||
|
||||
```bash
|
||||
cd operate/hosts/<hostname>/secrets/
|
||||
# Edit the master secret
|
||||
cd secrets/master/
|
||||
agenix -e <secret-name> -i ~/.ssh/id_rsa_agenix
|
||||
|
||||
# Rekey for all hosts (auto-encrypts for each host's public key)
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey
|
||||
|
||||
# Add rekeyed secrets to git
|
||||
git add secrets/rekeyed/
|
||||
```
|
||||
|
||||
When host SSH keys change (e.g., after instance recreation), just run the rekey command to automatically re-encrypt secrets for the new keys.
|
||||
|
||||
### Rebuild Single Node
|
||||
|
||||
```bash
|
||||
|
|
@ -172,11 +184,22 @@ colmena apply --show-trace
|
|||
|
||||
### Secret Decryption Failures
|
||||
|
||||
Ensure public keys in `secrets/secrets.nix` include:
|
||||
- Your admin SSH key
|
||||
- The host's SSH key (from `ssh-keyscan`)
|
||||
If secrets fail to decrypt on a host:
|
||||
|
||||
Re-encrypt if needed:
|
||||
```bash
|
||||
agenix -e <secret> -i ~/.ssh/id_rsa_agenix
|
||||
```
|
||||
1. Check the host's public key is set correctly in `operate/hosts/<hostname>/default.nix`:
|
||||
```nix
|
||||
age.rekey.hostPubkey = "age1...";
|
||||
```
|
||||
|
||||
2. Verify the master key can decrypt the source secret:
|
||||
```bash
|
||||
cd secrets/master/
|
||||
agenix -d <secret-name> -i ~/.ssh/id_rsa_agenix
|
||||
```
|
||||
|
||||
3. Re-run agenix-rekey to regenerate host-specific secrets:
|
||||
```bash
|
||||
nix run .#agenix-rekey.x86_64-linux.rekey --force
|
||||
git add secrets/rekeyed/
|
||||
colmena apply --on <hostname> --impure
|
||||
```
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,12 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-0;
|
||||
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-rsa QGRkYA
|
||||
DWb37kQ5fhkraWg90TMjxv49VsAIlCnOeGhKHrYeGUvDFR5CP6o/mtMLRsBUaY3I
|
||||
UkczSB7cPqejc+1rYEITI1QpCC1EKet8WYN3DwaHLHOnBQyaqCaPrL8dWARJsba8
|
||||
GdncimCGXbuNR9o2kDe0CcsNVYm16rfTaGxze+LoWzrUESSvx6/oy7+Lc3J3ZsBU
|
||||
n9hekGOhC0ra0ItTaa6I+JX3OjzWDkAum+dUdgsjZ51s+5s+hADOvnbaTLlaj/a7
|
||||
gBShGo558jwiwLXaZ3Tsv+UWAkmWJBj18LCLF61TXIOSDEQ1yRq3qceUiS0+M6hv
|
||||
F8vKBx+pg+yco3Kg6WJOQ0jozwrZTxeQS3PF+HMEkxtZ0LCoorQ58Ud3n5NBUFWs
|
||||
cQj77qZpxok9p5CM5IxsXhUZIAly+jGj2Pm25cLjlI2iBvn+lJmFhHs9qkWIjv+L
|
||||
+OWiqQTjhMCzLT+zfNVP1AfpCuz9mOQnqjrY/OyMbMVrfaDlBO7OcHbM6k8PDmB3
|
||||
|
||||
-> ssh-ed25519 9wiyCA 60M7bcZMRZT/Y4Rsj4QMvxDDtly1vUNULHhn60zF1BE
|
||||
btWbynM9Nlrk7H++y6LCHnuSi0XESrC7JushDnkuDRo
|
||||
--- v50l8afGolaf+RSC34DTvq+NYvWTCG6pvMGqy2ZAZxg
|
||||
@ÜÛ Ò8׫Èmô‚(£¨*&¥ŸÊñ¾ÀŠÂ’ß<C39F>·9Œ0{;ôÈy1R&/ÿÆ<C3BF>%cþ{X0!
ŠÂ›ì<E280BA>Ì=8™¤‚_ÝZiK”„ÜÚ1”RnU§]u³ÀŸXLòY³
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILUJR7tGcQEwWj9lGEoC2sqWzxFif1BFddYzZfcfTFp+"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILUJR7tGcQEwWj9lGEoC2sqWzxFif1BFddYzZfcfTFp+"];
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-rsa QGRkYA
|
||||
nfOvsCD1a+BI7iLi8pHUbWXVd/1bD1SbfncHkCaZMKL3Eu1s4tkkAYDdBJuDjB6w
|
||||
iX7WymzwE56AxNWbjJ9oytNNuFWVRnwij9JRddZrqN0BuAf9suz9DShw/ZhS5WpV
|
||||
3iqu0sEFiDfS4o0RYbO8N5VEctCVlKU6JDuuR59NszpveH+OOo9Cf8ktI+D/hBxr
|
||||
aK2hNCyro/XvFXnBKx8HCrrnN/2c108DGUb6CbTfeBTf16nen+Dr4dhe8pwzQMgf
|
||||
phC1S7RAR2J7Gg6u9elC+mUE9Q8uQvR2KISr2x5vTjxdeaXNnVu1nt2H28LNhUDO
|
||||
UfjXrmGzWnX/oMCjTy3IhVqMHj+5KN9NrVZW7nD6bggwuNCqzgD4D8DfzN/EBkZ1
|
||||
gxvhLN1iMDnLPXDxjr/V8+SUzQF7b00N/yhBBiUW+pzcOPIXZ3I4WFzJnMLTy8+r
|
||||
D07MM6OtYzYJPj6054kRPJlZs5bJTwyqHisK9yaKu29QA/BBCD6YctrzmkRR4Bof
|
||||
|
||||
-> ssh-ed25519 9wiyCA UREl4v6fTZe2pRMazoHQTDtixfBfuJ0pobjND06F+iM
|
||||
3RXyb5/AN6JMdlYvbKfrRfAVwhi9LAzewNfUT2H/ZBs
|
||||
--- YHrW11yRAjE01fgUjBllbLwaXx7fofsmay0y8YrZ1GQ
|
||||
<–ÇXøž<C3B8>1ÔwuŠr0¢]½u°Q¥àò]wEp©Ä<Tin ÷÷J4»arRK'v5FðK.ô¥¡Ê¶ì¢Ê¬<C38A>>TωÏ{£?XüZü.òîCQe$f~$M6
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,12 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-1;
|
||||
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-rsa QGRkYA
|
||||
UVvVR1AjoXWrlZ0KCf5t+Fust/9cD7YmgWcmEFtMnbWw0b7Ns3PmXJ9LfDeVz6Dp
|
||||
hBbwlEx0eKZdT9NFYRKUJQ0uyhgm0jpuHnDTroauSy0l5yiZCrAoSu2kE4VTYSqr
|
||||
nW36MFwhwW72ttWwDB4K6iMkX9/ttyVzQDCCbsVFT/miWQOnVYJ6/Zxqf6LxXw+2
|
||||
9shypscJcA1IeMXXwwd0kK+zl1dYhqWMiILqSLRxqMUjTkh9HyODKknjfoQ2kMLs
|
||||
mSkew1+t1/Z4AaC69vztStZBIeNt4WlrtqDRmAVzj4pWzcQGo0Tr+sV6UU2f6rca
|
||||
BJqE4SF0pCA3laTbEyvhRgtfvQ6KlYCnCHwAF+oOaCoEvArn0dK83HcjX35txxr+
|
||||
ZD43tgQ2kEPSNxUIlJ+SfMFzTrN8UvF5tgbbyv+4GpL1oGlPPvz66WsKX76K199w
|
||||
T5CMgna4IH9uZstEZCV+/53nEjKaW7YAezHeCgopcQYxscIh0Gu8MiHTWKPztyFI
|
||||
|
||||
-> ssh-ed25519 o8Va9g Ov+y+2crfYP+z33Re7W32CF03gPXOFhS1Sa+Pk/n9W8
|
||||
rwvlQtCSbuW8xEI5mQrnGgQuVh34bFjnjF+HxdNnlZw
|
||||
--- O71Uoai3gZMhQowUKAMHLqxS/2aIkjmTXz3lVQSa4F0
|
||||
’_‡&Ñï^IHì˜r‹nÃBCˆïÁ ˆ|SKB³ŠM<C5A0>¶<ÄdFÈŽ5µz>é¿!kk·lÕ!<21>ãRê4…2]ô’B!‚hm®GåÓçCVVœ .„ìÍ
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKbgB/dhJKY4lX8jmvY0C9enBHDnP5sx5GOYqFQlR+op"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKbgB/dhJKY4lX8jmvY0C9enBHDnP5sx5GOYqFQlR+op"];
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-rsa QGRkYA
|
||||
pL3LXLX8e8zzCiuF6vH1ELnnGWAzdFsW/PybRMSXGXYnM4f+dNmSow+h2MF+u+C6
|
||||
CRZpB16SW98VpLscwXmD/iOpCERXAnBqvmG1XdIDUYeKOke5K1n+93+l3pb/eezV
|
||||
04/tgGTkdAedqprAxyyFgwBMfWlbi/+IU4OKCSuKvZOdiLiELHGAmSHCHrKnsitn
|
||||
MZEDvc5XYzSLmA2+umtNiGj9BPMPu/lkKN1tWqiWNXt5it8Zqj/ErVXIOm7byk5H
|
||||
V2/8y14GCA5LBU900VDLiTx0fwyegoy2t9IOioDdpM2KSmzUBugQV8vQFYsQPzGN
|
||||
xzRiG7nx+L42vCwvLg5okWyugYN2HhqUstHuYmzksL7rMjTGzrurlNzdYoGRH8R7
|
||||
lQLbr8SFq/7zuI2Jt59ZiF9rR/2qHITPwyiZ3GoYBOjVM9EhHUg8bBvEWXkyS6dT
|
||||
+Ryb1mlNrn5DBHRb0pSAEvLkDoyw23ZvhgKEmXZ524MkvmBnPNwn2ctlDmRv0SIa
|
||||
|
||||
-> ssh-ed25519 o8Va9g qgFXCMZN95QUlDu8CQlxgOHC7CfgKe9lhWWFr5m1P3c
|
||||
lyEdtMmjlEAp3TdKw6fbx/APBtUgDVuesUbxisdHZ+s
|
||||
--- 3rHayoYA0fZM2VNckGhTwSDZPREKcKWG/tbZC7WB/Ck
|
||||
^V`·á¤f»í4Ú/œêÑ?&9þaK$qiL1AQºJ~åBØ•·?™wìD'çµWï„N2!î%¤<><17>Ï<EFBFBD>ÉÿÛ–‹$f¢PχÅã™mŽzgYœ.Ö ŽÀÙ°Ø
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,12 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-2;
|
||||
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> ssh-rsa QGRkYA
|
||||
pbrOgDiO/3XWQgDL6UQx8cItdLq38zNigrAhEUQNJGAJU/qBuPT+2PV6siaXJirP
|
||||
dr3eeuTDIhSJhsjJR3YVxxFCHV+xUm391Ic4ywIDiuF6IjGT9SNb+T9UNrhPIySV
|
||||
jpSi0ES6/QXcqHRc96cmrq/khJ4+02IknkIRa0VqzmAqvMw2uOLBYT1gAnS7ncpY
|
||||
Kvgs+JIjO6WEsE7byjKrtzH+fJnzGXq/t+YkvO3RzGQu/2QqLcn/vx+uBQHCiUr5
|
||||
IN4JafmdyDM6FArjvZvngRC0VcfQxGUoyoSzAMoMFX48JJ83J7c2mzEhZ8ai4ZmN
|
||||
Hkcbm0F6BSJw0pvyvURyLi/M1Weyoef3bpgXtH9PsJr1mlMKEW8LjgLlu15cQG9V
|
||||
JJlPFRUvf3/lzL3yGDETHOYCFeXrH+TTp7KLYIdHMWhHhQMJ68OKkpHnnJaQPStF
|
||||
hy8xAmI6z3/kQKrFifL8SAKZkWwVPxq3mdsbBRaLM9t3spXT8FhCDbYgAntLAmCK
|
||||
|
||||
-> ssh-ed25519 mCobKg d7hP1AFvHdXCUGtOh01/06IEHmtHHSH/wJTJEBOjWUs
|
||||
G1uS06aAaZE/ReQ9q/FTzc586dhSZX95fTBYwa2TZ6U
|
||||
--- 4R5LkLFZoBfnPTP//TDfnP0JIajNo7rLIIrqEVtDzyo
|
||||
þÚ!dIûWúHMFkwÈ(ýÀÚç¯= :Ó²šÌoOŒßý«êdäF„eÿ²F©åÇhŦUÔ¨|ѳɥmÙ6<C399>=n<NtEÜž½Ä<C2BD>Žz.ƒªi7˜Ù<CB9C>Ïš+UÝ
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzE/CkZokri8tfeuA9EWompjmBVPC07FV0JLkfDsv5l"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILzE/CkZokri8tfeuA9EWompjmBVPC07FV0JLkfDsv5l"];
|
||||
}
|
||||
Binary file not shown.
|
|
@ -4,10 +4,11 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.235.48.77";
|
||||
targetHost = "172.236.226.134";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,10 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-3;
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
@ -59,7 +65,7 @@
|
|||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
(if builtins.elem name ["ncm-3" "ncm-4" "ncm-5"] then nomad_1_11 else nomad_1_9)
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
|
|
|
|||
114
operate/hosts/ncm-3/default.nix.backup
Normal file
114
operate/hosts/ncm-3/default.nix.backup
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
name,
|
||||
nodes,
|
||||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.235.48.77";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
};
|
||||
|
||||
networking = {
|
||||
networkmanager.enable = true;
|
||||
# Linode is no longer able to connect to Linode Object Store via ipv6, and and linode object store is now advertising
|
||||
# ipv6 addrs via DNS. This is the simple and dumb solution to fix the problem of Nomad not being able to fetch
|
||||
# artifacts from object store.
|
||||
enableIPv6 = false;
|
||||
hostName = "ncm-3";
|
||||
nftables.enable = true;
|
||||
firewall = {
|
||||
logRefusedConnections = true;
|
||||
logRefusedPackets = true;
|
||||
checkReversePath = false;
|
||||
# always allow traffic from the tailnet and internal network
|
||||
trustedInterfaces = ["tailscale0" "enp0s5" "podman0" "veth0"];
|
||||
allowedTCPPorts = [22 80 443 24017];
|
||||
allowedUDPPorts = [config.services.tailscale.port];
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
hostname = name;
|
||||
pkgs = pkgs;
|
||||
})
|
||||
];
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets.tailscale_auth_key = {
|
||||
file = ./secrets/tailscale_auth_key;
|
||||
};
|
||||
|
||||
age.secrets.linode_cli_pat = {
|
||||
file = ./secrets/linode_cli_pat;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
python3
|
||||
restic # For performing backups
|
||||
(writeShellScriptBin "list-peer-nodes" ''
|
||||
#!/usr/bin/env bash
|
||||
${pkgs.tailscale}/bin/tailscale status --json | ${pkgs.jq}/bin/jq '.Peer[] | select(.Online==true) | select(has("Tags")) | select( [ .Tags[] | contains("tag:ncm")] | any).TailscaleIPs[0]' | tr '\n' ' ';
|
||||
'')
|
||||
];
|
||||
|
||||
users.users = {
|
||||
root = {
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
sfos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
# TODO Initial password and authorized keys need to come from .env, perhaps using nix-edit
|
||||
initialPassword = "Test.123";
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
# TODO caddy needs a plugin that watches the nomad node list for specific tags that cause them to be reverse proxied
|
||||
# from this host system
|
||||
caddy = {
|
||||
enable = true;
|
||||
# package = pkgs.caddy.withPlugins {
|
||||
# plugins = ["github.com/acaloiaro/caddy-incus-upstreams@v0.0.0-20241228235755-786cd3b6a9dc"];
|
||||
# hash = "sha256-yjqXgo7WiJPBVmN3+O8Wq9Nxd1xU8KrXW7Hv7Elcf7I=";
|
||||
# };
|
||||
# virtualHosts = {
|
||||
# "https://adrianofyi.incus.adriano.fyi:443" = {
|
||||
# extraConfig = ''
|
||||
# reverse_proxy {
|
||||
# dynamic incus
|
||||
# }
|
||||
# '';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
openssh.enable = true;
|
||||
tailscale = {
|
||||
enable = true;
|
||||
authKeyFile = config.age.secrets.tailscale_auth_key.path;
|
||||
extraUpFlags = ["--reset" "--advertise-tags=tag:ncm,tag:nomad-server" "--accept-dns=false"];
|
||||
};
|
||||
};
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
};
|
||||
services.nomad = {
|
||||
enable = true;
|
||||
package = pkgs.nomad_1_11;
|
||||
extraSettingsPlugins = [pkgs.nomad-driver-podman];
|
||||
enableDocker = true;
|
||||
dropPrivileges = false;
|
||||
|
|
@ -57,7 +58,7 @@
|
|||
interface = "tailscale0";
|
||||
};
|
||||
"public" = {
|
||||
interface = "enp0s3";
|
||||
interface = "eth0";
|
||||
};
|
||||
"private" = {
|
||||
cidr = "10.0.1.2/24";
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEhsV2VvUSBYYmVT
|
||||
WmFQZk5VOG10NnZBWjVvYWJGYVV0dGNzeTdhVkphaGVuR2tYdzNFCnVRVllhYThR
|
||||
U3p6SlE1T01zdTBTV25RSVdGU29pREJmUFVOL1VrckdkSVkKLS0tIGl5WGE4UnRr
|
||||
V2txaG9kcjk4c3QwSm54TWllVHBiWm5ZcXMvYUNVMzZjMG8KTZ5QU6IK1ueizdo2
|
||||
4CWq5fTxo0Y/yjB1QvkNCZAYYS0PiCThUxX82U7nOllUB6dZ/ODA9oitXum2FXd2
|
||||
RjAZYr0SY3sLHbmOV932SyYiQKZRxTVhEBFwwxV98bong87d
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHuJNBURq4NZpt+EgQ/750HCqu43tFbV0UT4Vpz4drId"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHuJNBURq4NZpt+EgQ/750HCqu43tFbV0UT4Vpz4drId"];
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IEhsV2VvUSBkMXhH
|
||||
Zi9Tb2sxSjFFbVJRR25LSWFwT1F2ZEY1dEduRlBRRmk2TXZuQlRzCm1kTEE0bGFQ
|
||||
UTZXM3VveGliN0ZDWTl2RlRBT3NHYnhrTTJ1QlZObU1KNFUKLS0tIC9ocXZRVEFz
|
||||
VHBWRzFHVktyaG4yTG1CeFM0SmVxZ2x4bzNDQXB1aHVWOE0KgPi29as8x5Blrzh9
|
||||
jzhvnvjtBUnBimmRkZG8ZFNiaBo0nF73itnEhjPAOi2wS4BKg2SQm7n93RjVd8EZ
|
||||
Id7VonE4Bf7CIkDtCx0fNqzadjhfEfdjdo6E2xXvti4YbQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
|
|
@ -4,10 +4,11 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.236.244.127";
|
||||
targetHost = "172.236.226.94";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,12 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-4;
|
||||
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
@ -59,7 +67,7 @@
|
|||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
(if builtins.elem name ["ncm-3" "ncm-4" "ncm-5"] then nomad_1_11 else nomad_1_9)
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
|
|
|
|||
114
operate/hosts/ncm-4/default.nix.backup
Normal file
114
operate/hosts/ncm-4/default.nix.backup
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
name,
|
||||
nodes,
|
||||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.236.244.127";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
};
|
||||
|
||||
networking = {
|
||||
networkmanager.enable = true;
|
||||
# Linode is no longer able to connect to Linode Object Store via ipv6, and and linode object store is now advertising
|
||||
# ipv6 addrs via DNS. This is the simple and dumb solution to fix the problem of Nomad not being able to fetch
|
||||
# artifacts from object store.
|
||||
enableIPv6 = false;
|
||||
hostName = "ncm-4";
|
||||
nftables.enable = true;
|
||||
firewall = {
|
||||
logRefusedConnections = true;
|
||||
logRefusedPackets = true;
|
||||
checkReversePath = false;
|
||||
# always allow traffic from the tailnet and internal network
|
||||
trustedInterfaces = ["tailscale0" "enp0s5" "podman0" "veth0"];
|
||||
allowedTCPPorts = [22 80 443 24017];
|
||||
allowedUDPPorts = [config.services.tailscale.port];
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
hostname = name;
|
||||
pkgs = pkgs;
|
||||
})
|
||||
];
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets.tailscale_auth_key = {
|
||||
file = ./secrets/tailscale_auth_key;
|
||||
};
|
||||
|
||||
age.secrets.linode_cli_pat = {
|
||||
file = ./secrets/linode_cli_pat;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
python3
|
||||
restic # For performing backups
|
||||
(writeShellScriptBin "list-peer-nodes" ''
|
||||
#!/usr/bin/env bash
|
||||
${pkgs.tailscale}/bin/tailscale status --json | ${pkgs.jq}/bin/jq '.Peer[] | select(.Online==true) | select(has("Tags")) | select( [ .Tags[] | contains("tag:ncm")] | any).TailscaleIPs[0]' | tr '\n' ' ';
|
||||
'')
|
||||
];
|
||||
|
||||
users.users = {
|
||||
root = {
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
sfos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
# TODO Initial password and authorized keys need to come from .env, perhaps using nix-edit
|
||||
initialPassword = "Test.123";
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
# TODO caddy needs a plugin that watches the nomad node list for specific tags that cause them to be reverse proxied
|
||||
# from this host system
|
||||
caddy = {
|
||||
enable = true;
|
||||
# package = pkgs.caddy.withPlugins {
|
||||
# plugins = ["github.com/acaloiaro/caddy-incus-upstreams@v0.0.0-20241228235755-786cd3b6a9dc"];
|
||||
# hash = "sha256-yjqXgo7WiJPBVmN3+O8Wq9Nxd1xU8KrXW7Hv7Elcf7I=";
|
||||
# };
|
||||
# virtualHosts = {
|
||||
# "https://adrianofyi.incus.adriano.fyi:443" = {
|
||||
# extraConfig = ''
|
||||
# reverse_proxy {
|
||||
# dynamic incus
|
||||
# }
|
||||
# '';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
openssh.enable = true;
|
||||
tailscale = {
|
||||
enable = true;
|
||||
authKeyFile = config.age.secrets.tailscale_auth_key.path;
|
||||
extraUpFlags = ["--reset" "--advertise-tags=tag:ncm,tag:nomad-server" "--accept-dns=false"];
|
||||
};
|
||||
};
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
};
|
||||
services.nomad = {
|
||||
enable = true;
|
||||
package = pkgs.nomad_1_11;
|
||||
extraSettingsPlugins = [pkgs.nomad-driver-podman];
|
||||
enableDocker = true;
|
||||
dropPrivileges = false;
|
||||
|
|
@ -57,7 +58,7 @@
|
|||
interface = "tailscale0";
|
||||
};
|
||||
"public" = {
|
||||
interface = "enp0s3";
|
||||
interface = "eth0";
|
||||
};
|
||||
"private" = {
|
||||
cidr = "10.0.1.2/24";
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHM2UGF2USAvOGNR
|
||||
SCtjd2JVNjdUZWJSNFdCRWxPL2tjaUxpS2JxdEdHdjMzNjJhbWxjCkxGN2F2RHVu
|
||||
OWJFUXZYV09GYzhXdGNndHcwcXVPMC9odUhpT1YrMWF2ZmcKLS0tIDc1M3VzL1Vs
|
||||
MHg4R2pvbm14ZXFGNVFlSUlKOGwvc050RTRURkp6T3lveE0KtY5PWXv3UrVevElc
|
||||
zGQ92CajQ9LMiE8bn6rhF6E6mkVVs9CIbGSympApNwHtSFJZEeaVNzqgWgVQWvO2
|
||||
hDLD/T1e9kSwfKI+dSSqS7Wx3hyHiAgdYVOYSIckYjdZKpoM
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFXD8JoGWsCP/4GZyqKjP+PCMffJOXnsWSZuBJ7czUC"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEFXD8JoGWsCP/4GZyqKjP+PCMffJOXnsWSZuBJ7czUC"];
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IHM2UGF2USBRWU5Y
|
||||
T2pDUlpEdXM5NHcwTDMxUzN6c2JCVDBucWJGdUh5OGJoSUtDRnljCjNWalk2eTB6
|
||||
OG5kd1FZMW9yYndwUk5kYmN5Y0tDYXczazlLYmJQZnlKREEKLS0tIGU2ODZyZ1Fz
|
||||
WDNIQmh2QlVlQW1ZcEtrQ1RWZjdNV2ErZ3lHWWFXMzlMUmsKxVqwWDYTOYLXuGCb
|
||||
Bhi3H+xd1uTO74FCjhAoCsaaHcjXsqw5p1fJCHzVwjBFvf3C2q/bCKUVVPqz9LcR
|
||||
JJGJ4SX00difYqgTdUBRwSpQ1OvxtHWB5UPcN20BdUc/Xw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
|
|
@ -4,10 +4,11 @@
|
|||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
agenix-rekey,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.235.48.213";
|
||||
targetHost = "172.236.226.82";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
|
|
@ -34,6 +35,7 @@
|
|||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
../rekey.nix
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
|
|
@ -42,6 +44,12 @@
|
|||
})
|
||||
];
|
||||
|
||||
# agenix-rekey configuration
|
||||
age.rekey.storageMode = "local";
|
||||
|
||||
age.rekey.localStorageDir = ../../../secrets/rekeyed/ncm-5;
|
||||
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
|
|
@ -59,7 +67,7 @@
|
|||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
(if builtins.elem name ["ncm-3" "ncm-4" "ncm-5"] then nomad_1_11 else nomad_1_9)
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
|
|
|
|||
114
operate/hosts/ncm-5/default.nix.backup
Normal file
114
operate/hosts/ncm-5/default.nix.backup
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
{
|
||||
name,
|
||||
nodes,
|
||||
config,
|
||||
pkgs,
|
||||
agenix,
|
||||
...
|
||||
}: {
|
||||
deployment = {
|
||||
targetHost = "172.235.48.213";
|
||||
targetPort = 22;
|
||||
targetUser = "root";
|
||||
buildOnTarget = false;
|
||||
};
|
||||
|
||||
networking = {
|
||||
networkmanager.enable = true;
|
||||
# Linode is no longer able to connect to Linode Object Store via ipv6, and and linode object store is now advertising
|
||||
# ipv6 addrs via DNS. This is the simple and dumb solution to fix the problem of Nomad not being able to fetch
|
||||
# artifacts from object store.
|
||||
enableIPv6 = false;
|
||||
hostName = "ncm-5";
|
||||
nftables.enable = true;
|
||||
firewall = {
|
||||
logRefusedConnections = true;
|
||||
logRefusedPackets = true;
|
||||
checkReversePath = false;
|
||||
# always allow traffic from the tailnet and internal network
|
||||
trustedInterfaces = ["tailscale0" "enp0s5" "podman0" "veth0"];
|
||||
allowedTCPPorts = [22 80 443 24017];
|
||||
allowedUDPPorts = [config.services.tailscale.port];
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
agenix.nixosModules.default
|
||||
./base-system.nix
|
||||
./hardware-configuration.nix
|
||||
(import ./nomad.nix {
|
||||
hostname = name;
|
||||
pkgs = pkgs;
|
||||
})
|
||||
];
|
||||
|
||||
boot = {
|
||||
supportedFilesystems = ["btrfs" "ntfs" "vfat" "ext4"];
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
age.secrets.tailscale_auth_key = {
|
||||
file = ./secrets/tailscale_auth_key;
|
||||
};
|
||||
|
||||
age.secrets.linode_cli_pat = {
|
||||
file = ./secrets/linode_cli_pat;
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
helix
|
||||
nomad_1_9
|
||||
nomad-driver-podman
|
||||
jq
|
||||
postgresql # So hosts can perform postgres system backups
|
||||
python3
|
||||
restic # For performing backups
|
||||
(writeShellScriptBin "list-peer-nodes" ''
|
||||
#!/usr/bin/env bash
|
||||
${pkgs.tailscale}/bin/tailscale status --json | ${pkgs.jq}/bin/jq '.Peer[] | select(.Online==true) | select(has("Tags")) | select( [ .Tags[] | contains("tag:ncm")] | any).TailscaleIPs[0]' | tr '\n' ' ';
|
||||
'')
|
||||
];
|
||||
|
||||
users.users = {
|
||||
root = {
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
sfos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = ["wheel"];
|
||||
# TODO Initial password and authorized keys need to come from .env, perhaps using nix-edit
|
||||
initialPassword = "Test.123";
|
||||
openssh.authorizedKeys.keys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1"];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
# TODO caddy needs a plugin that watches the nomad node list for specific tags that cause them to be reverse proxied
|
||||
# from this host system
|
||||
caddy = {
|
||||
enable = true;
|
||||
# package = pkgs.caddy.withPlugins {
|
||||
# plugins = ["github.com/acaloiaro/caddy-incus-upstreams@v0.0.0-20241228235755-786cd3b6a9dc"];
|
||||
# hash = "sha256-yjqXgo7WiJPBVmN3+O8Wq9Nxd1xU8KrXW7Hv7Elcf7I=";
|
||||
# };
|
||||
# virtualHosts = {
|
||||
# "https://adrianofyi.incus.adriano.fyi:443" = {
|
||||
# extraConfig = ''
|
||||
# reverse_proxy {
|
||||
# dynamic incus
|
||||
# }
|
||||
# '';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
openssh.enable = true;
|
||||
tailscale = {
|
||||
enable = true;
|
||||
authKeyFile = config.age.secrets.tailscale_auth_key.path;
|
||||
extraUpFlags = ["--reset" "--advertise-tags=tag:ncm,tag:nomad-server" "--accept-dns=false"];
|
||||
};
|
||||
};
|
||||
system.stateVersion = "24.05";
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
};
|
||||
services.nomad = {
|
||||
enable = true;
|
||||
package = pkgs.nomad_1_11;
|
||||
extraSettingsPlugins = [pkgs.nomad-driver-podman];
|
||||
enableDocker = true;
|
||||
dropPrivileges = false;
|
||||
|
|
@ -57,7 +58,7 @@
|
|||
interface = "tailscale0";
|
||||
};
|
||||
"public" = {
|
||||
interface = "enp0s3";
|
||||
interface = "eth0";
|
||||
};
|
||||
"private" = {
|
||||
cidr = "10.0.1.2/24";
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFp6MkdLUSBxOUpu
|
||||
ZU1yOXB6WlUvcDNPanA1MFhtQ0lVZWlyUlV0dGZCQ3VlYUo0MUFRClZCMWdpb0ls
|
||||
Y2htVTN0SHdTajArdm9odVZJd1I3NmZuZ0FYUXJodGZ4NVkKLS0tIDUwUUdZYkJs
|
||||
T3ZIcytOeEpxUnlURnlFdkE1VVBTNHZiVXFZR2hUOUt6NGMK4rvngvo0nAiUxeyT
|
||||
qj5d3EcYEj4AZOuy0nzlCXpqIqqCWRDctKF30uXv/6HSL1KpHq3o6bJatsHtu/73
|
||||
mUKApnNT+AW+5LnJpt3n1ZCHGhHOUxOmrPCvaRtFtIPzf5+/
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
# Use ssh-keyscan <SERVER> to fetch the below keys for target systems (SSH server must be running on system)
|
||||
let
|
||||
in {
|
||||
tailscale_auth_key.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMqJFMTeWs/TpKNbVTp9S5kU8XVqoV2mmHq3p7ZEIxfy"];
|
||||
linode_cli_pat.publicKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCx/tvR11RUMbYaauuHPxR3j79vm1Hxg+Y3LXR+rLgZ7N/2ulvIzLLZgVuIUbmJHDqkp9Au5zZPMZjsKbaqQ8V75wSEcyaSMbaxC9PaNDCwEHMJWaz8XPQe5IjVRE5O+4sTyh7ZBx+NMQmPcQbrNInoKuy4EjFmwTW/t0xYo/sCrC0NX0cCyeBwii2JdFXytXfxF+RMzGNXw1xfcOFJe6F7JdS/Cpf/0fe+VmNg8d0nic4Obcb/djYsRLAAC6Cvb+4i3EBZWl+9Ih9hId8bFCRKhI6TmGT2z4YUTa+v+3j/JZUh1gD5n4vRGf8QjLj9N6DrBnKcbywwqyqnLhTLgBBN35rcLdU1k3n0NorRRDCU0Lg/ejsFe3oi2FmOwNmmd8zqBNZHjJTi5Wy63EXMFwHltEY2M+hAhgWsQ5U4zuVPgv1HfD6LYPodRwhdZivwTNr2IClAiVVxR//O0WtrRXrrEM5uudj+Y30/ah7bn9Mje86UV0TqfS2tdjtMkySHL+M= adriano@z1" "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMqJFMTeWs/TpKNbVTp9S5kU8XVqoV2mmHq3p7ZEIxfy"];
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFp6MkdLUSBScFA0
|
||||
Q29ITEM1ajJlbUJDNHJwNnAxeHNQWFJLbkdpWml5R3EwbVZPcEMwCkE3Znk5S042
|
||||
eUNOWTdSTE9JcS9hV25GV3hOcjczVDhxbnlwZlBzMXYySzQKLS0tIG5GZmZra3Bu
|
||||
SmVVd3VoYU0zRkd3SWNSODhIRkN2cGdubC82S2U5RGNSaG8KJn0bYumsij87mJsa
|
||||
fV/a+M/Yr22+/0swdwt4Gd+UBxDxDnNCPjp97hsb+H8glq1OvP809IAEGRhTCPqR
|
||||
rPRkl0VUkRv/k9fO7wZMN/tbXZSiYe/yt8wJGcXJMDaPow==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
10
operate/hosts/rekey.nix
Normal file
10
operate/hosts/rekey.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{...}: {
|
||||
age.rekey = {
|
||||
masterIdentities = [
|
||||
{
|
||||
identity = "/home/adriano/.ssh/id_rsa_agenix";
|
||||
}
|
||||
];
|
||||
# Note: storageMode and localStorageDir are set per-host in their individual configs
|
||||
};
|
||||
}
|
||||
10
operate/rekey.nix
Normal file
10
operate/rekey.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{...}: {
|
||||
age.rekey = {
|
||||
masterIdentities = [
|
||||
{
|
||||
identity = "/home/adriano/.ssh/id_rsa_agenix";
|
||||
}
|
||||
];
|
||||
storageMode = "local";
|
||||
};
|
||||
}
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 MpoiaRFtOff7Ycz6vGqkizDZqgWWtcAxqKbELUhZ9WI
|
||||
ggFrXOKdX5uwfOYHRi5LFnTh5zv/M7frmtjvEOcsVpg
|
||||
-> pJvO.-grease 'vNWX 6le >G JvAYfDR
|
||||
NdaJLcjQA3gpk3y9qwq3uekNGfclTG47o0PSoJK2LBpfY/k8Gw
|
||||
--- gkbYjfJNcz7opJRiWgTUNQwq9eIcOcJfFTHtbMnDYYA
|
||||
ÖÓhҤ~uş¬ł˘ä"Wr“űĎ1ą¸ě^aĺŠíEŽąđň>ńU$ä˙ÝÝ!Ż:S¤ő7Â:ŗ̌şźl C܉Ƶé–÷Ý(EŹ‹¦îÓ÷ĆŢ{î“ń<>|ţű&ő
|
||||
-> X25519 P7v8KEsgsWU0NdEgT/VE7mP06IBsrPQx2KupSMg/IVg
|
||||
2Ou6ekmQjmAMz0CnUFh4OIH5sKuffdr9yhgKviozsQ4
|
||||
-> 3v-grease *E+u# aX/^VHm# <v6 Bw\c
|
||||
CazGEusZ8MsQSJrFjhhUr4elARTjZq6GZSExxzgXsKA
|
||||
--- 1ezFzMiL168P+rVExAwOasFl/6MsmCf2VQ6He/aEr6U
|
||||
„˜?¾£UOO2¸fijíyñú§üŒP9Ï1ÐF<C390>Û\ÿÉ!\8bÄ}$ØØêu¢æœy)sY‰k©éÜ©-¥¤C›<43>F¹}AÆDл
|
||||
” ÿ¤çîèîwë©„’øÞcHœÕ’
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,8 +1,10 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 33iPaPNi2FvCs8OeFdn+Y3OdHYQW0ChfW6JaGOoek0E
|
||||
lTBZv3kxjvb+IwmZI773E6ZgagZsrWHwFazQpz7yJ+8
|
||||
-> lfnR9-grease qo>< ?#/F;jKX
|
||||
qKcaXyL6vMrvWA6ioA4S8eo52CsQLbIwbuCxLDHcbqm/T33DR0EqgSrVaGANOgtU
|
||||
+oLPaYTB7tvT+A
|
||||
--- dz4hwXJSFvg6ShENBdnvMwiJpl7iNCYmQEbiRSIn/fs
|
||||
{¥Õ¸%:÷H%ÅUÙ*âq<C3A2>ĶIs’~™ƒ"Éâܹ³%©ŽK õ5³˜Bxt6÷ê}ÓÔ7óý;6ÑÏ’ž=÷6ó3µøÐùèávÎYjLÕ§|®4øÅô` j
|
||||
-> X25519 qzDVonozY6ZZbKhsIzkTXCk+KmmcvBDOPKnAheZa3B8
|
||||
Cl6mUUSjh95SOnZhPa4FjRDdk+PX6dYgJqot0SR/Vtw
|
||||
-> [<k87uJ_-grease
|
||||
wAwriEERz4XJF4flJjYF740Q6RWcvbVqrECbTHVGZ5YtowVUplaDVLSkkImpW7Xx
|
||||
WXnbg3EqxoTo8G9gjNAuPTSA+EKf8QVU
|
||||
--- bIsUxkIebGJVYt6yE5H5C7kpGmeAfgibREunUElmS3I
|
||||
¨Ę(aĚ<61>ÝěĘ6`ˇâ3±
÷7<C3B7>޸ 8]î
ŕ
|
||||
Á@m}ËDaŤîF÷!|ż6^TŽ ädAf|
|
||||
ŻŃ>_íN™4Űy‰›ĹĂn§űŕ[Nź¨Oüd¸E‰ęxDNş
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 Iv8Gsu+25l5E2G8hynodBW4iEgWrGhutlAAnh1hUdQw
|
||||
nWcivI47dmgTGFmyxeZ1lRt9W1eVwXHsAFY2QHOu3ag
|
||||
-> @*-grease Uz>{5 t:_mx$ f >
|
||||
x+ffUGIqocAyNhgcEaZTGjQ
|
||||
--- +A6E0O0Qs7zqoA5ymTEV9adTAPhKFdhpvrpnJa2jpHo
|
||||
1ŽBLĺÄŃŔVˇbĄ“ě=s¸
đľqĄĆçňľ<C588>ţš ßb˘gáe…¦îTaË8ĘKę
|
||||
lćóđ9q&BĎwZ v[ćĆ9žG#<23> XĎŔ)Ó#óĺQ‘¦żę§˘d
|
||||
-> X25519 9sNWiLY6KxSU2DN49wcZavVUWCUa6fTqyVbHKpCjPmw
|
||||
JyHrgVsTwmKf6Jswdlm9mCP6ApTT1FJ7YzDTPPKu2H4
|
||||
-> i'wFl-grease o$--T e>{
|
||||
LuHU+7D+d6eScRe8NRXqNoPxQqQMNf2yJvH1t4ILaKorxUZewlqymrZ0kDEal9fW
|
||||
JCjfwpLuGsQWi+88he6vZFO73CoOsFxwByPSQGxYOZSNcw
|
||||
--- nDBnuhOjuyxzAinrHlkunRFChSDt8l+0jT5SHprrJqg
|
||||
Õ¥€XqY¥écz¦¿lK¼ ’'ùãJóðf‚ž›¤W;s‰/SøOvÖíÆG¹aÉŸ¾&uL<75>ø4‰*ãô#5É阹Ëí\¿¿ŠT‹O𴇋sðæŽ'SÄsʆ
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 w3EJdXskGzIxAY0ez+JB6G6l7mP7BSTAhOUS/wsTL2w
|
||||
nrBtcMvV65t7LW/tZNYxaHsXdWjXmBBwnFkVpKGMDrQ
|
||||
-> }vFY-grease )q $7rpv.[@ 0-V.$~
|
||||
ojB+g60OX+6gI5HzE6mSeDF5KenNPx51+xKYefCaIMlBfS+CYQLVC89PjlV7mRnF
|
||||
kDWz/0windFATKUBbQTtZdYPrYgkWiAPc3wE
|
||||
--- hTT4E7hhHVPfxdf7uI/YdLQ/G1PP9vDtSm+a7vK6g8o
|
||||
nř9?_4÷VEÚÜ<óĚ˝ňpÔóčď9_Ą<5F>ľ`OĆAšfFáÜQ,}//¤LČo¨°Ě˘âÇIxfbNÂřę\—ť—ŹtkRj†ŕ"%H‰î"T3ŹEßä°úŻů
|
||||
-> X25519 N9ddAjqwpVr9smLTZoVA9In2Q1wK/UG5XN1OHVQK2ls
|
||||
KNdHlkoRSRKOE25kWfmv4nbpgz0NS7KVpTneMuNbCjk
|
||||
-> Htx-grease %ekB\"J F]YYbD_ =qG,ZU6 gG
|
||||
uniXe+Lwt+SR6vTxVaHuYErcSbcUdeno+37iRYgF2gJOGq6XtkTydE0eGxeLf94
|
||||
--- vBa90z3WJkbx3GuDJyQ4n5jTbuRKXzbhmL3I0hkVt04
|
||||
”ûsŠ²Ý“ipžTV¤ˆ‘_Mê3;¯˜¬Ê¯Ðms¹ù é¢ó9©tí’Js”<1E>ŸÜYˆÁß8Ÿ¤ZÏÈ'…(„ð–çÜjnÐpäÉÿŒá6u^E‰c~§)Éj.™¡Ð
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,8 +1,8 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 3Dt3qhNQnec9qQVEY2OuBWy+GtIrjxG1zBcLVpH+uHA
|
||||
gJzCy86W0+ussg+YLhPeKsZgwpeNra2Y4TsaGNrBjbU
|
||||
-> 3qT-grease b_u*j `#tX7BN {5
|
||||
9Zn8SSKLELDxTW6mxxIJZmKvvhcXwf8wZ8/88o3ql7osEMHVB8UZ2uTTzPJDULCI
|
||||
WGWMIZDBDi1ro/pIoDDU541XT4GlNjAQhnuRIKxCWqzz+VBHpTq29CrPFLkO
|
||||
--- aEbRZ+EbWkCBtdpCNj9a8aBBPIqECmXXpxYF7TVpPAo
|
||||
ÄAZøOJ:SŠML—œuxõ"’Ûçkpï½u!¼ˆð÷…÷_ÉñŒ
xXòÆÜâ¶½1ÜP-˜Ú;«oÕçXýôulâƒ(îûø¡ªTª¬/ßt
|
||||
-> X25519 bQlwmEf3KDPK10CQv1s4GaSKUIEb3o0FHy5xrp38VyQ
|
||||
ZTpnWyNQl30Xn3uXiVHB5nSZHA9vlBTu9wUoQyljLTM
|
||||
-> ?U+mu;R-grease 9eP ^9f .`1U*6h =R("_
|
||||
/o2v8vVLrdfw62XpxLD9ybWEbZOfd1Jx2VT1C7XmdVdW+zXk6VgvEFkKG/QCrLJ0
|
||||
cUsOVslcENuGuPzvbA
|
||||
--- C0HrEb7CZDpukncxIiQ62KEwYyTujRscXdn5GipGqtM
|
||||
5î2˝¬ ŢlĄű›üŤ•ÉnVăć«‘Ď+¸[[óńüQĺđžÉK‚$š0t>9c^šS¸ŰT-wXĽťőĚ<C591>ű<12>ů˘§>ŃčŽ4\¨O‘+K ϢËwµÖ°.šžëK×
|
||||
Loading…
Reference in a new issue