feat: Implement two-key SSH management strategy
- Add modules/security/ssh-keys.nix for centralized SSH key management - Generate role-specific SSH keys with geir@geokkjer.eu email: - Admin key (geir@geokkjer.eu-admin) for sma user server access - Development key (geir@geokkjer.eu-dev) for geir user and git services - Update SSH client config with role-based host patterns - Configure users/geir.nix and users/sma.nix with appropriate key access - Add SSH key setup to both machine configurations - Create scripts/setup-ssh-keys.sh for key generation automation - Update plan.md with completed SSH security implementation Security benefits: - Principle of least privilege (separate admin vs dev access) - Limited blast radius if keys are compromised - Clear usage patterns: ssh admin-sleeper vs ssh geir@sleeper-service.home - Maintains compatibility with existing services during transition
This commit is contained in:
parent
6a3a3abc48
commit
77e6b9a501
7 changed files with 221 additions and 10 deletions
|
@ -9,6 +9,9 @@
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
../../modules/network/network-congenital-optimist.nix
|
../../modules/network/network-congenital-optimist.nix
|
||||||
|
|
||||||
|
# Security modules
|
||||||
|
../../modules/security/ssh-keys.nix
|
||||||
|
|
||||||
# System modules
|
# System modules
|
||||||
../../modules/system/fonts.nix
|
../../modules/system/fonts.nix
|
||||||
../../modules/system/applications.nix
|
../../modules/system/applications.nix
|
||||||
|
|
|
@ -2,6 +2,13 @@
|
||||||
imports = [
|
imports = [
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
../../modules/network/network-sleeper-service.nix
|
../../modules/network/network-sleeper-service.nix
|
||||||
|
|
||||||
|
# Security modules
|
||||||
|
../../modules/security/ssh-keys.nix
|
||||||
|
|
||||||
|
# User modules
|
||||||
|
../../modules/users/geir.nix
|
||||||
|
../../modules/users/sma.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# Boot configuration
|
# Boot configuration
|
||||||
|
|
97
modules/security/ssh-keys.nix
Normal file
97
modules/security/ssh-keys.nix
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
# SSH Key Management Module
|
||||||
|
# Two-key strategy: admin (sma) and development (geir)
|
||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
# Global SSH daemon configuration
|
||||||
|
services.openssh = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
PasswordAuthentication = false;
|
||||||
|
KbdInteractiveAuthentication = false;
|
||||||
|
PermitRootLogin = "no";
|
||||||
|
PubkeyAuthentication = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Use modern, secure algorithms only
|
||||||
|
extraConfig = ''
|
||||||
|
PubkeyAcceptedKeyTypes ssh-ed25519,ssh-ed25519-cert-v01@openssh.com
|
||||||
|
KexAlgorithms curve25519-sha256@libssh.org
|
||||||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
|
||||||
|
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Centralized SSH key management
|
||||||
|
security.ssh-keys = {
|
||||||
|
# Admin keys for sma user (server administration)
|
||||||
|
admin = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPgzKS1N7+7+N1/8U8++1pl4hapDm6TOy0QhrfrYA8mz geir@geokkjer.eu-admin"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Development keys for geir user (git, daily use)
|
||||||
|
development = [
|
||||||
|
# Current key (keep for continuity during transition)
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHeOvTHIw+hZOAiWkIrz9t11UeGwxAMx7jN/1IIdgq7O geokkjer@gmail.com"
|
||||||
|
# New development key
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHukJK0Kc1YexvzF8PdqaqWNZdVffGoM6ePPMecrU6dM geir@geokkjer.eu-dev"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# SSH client configuration
|
||||||
|
programs.ssh = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
# Default to development key for daily use
|
||||||
|
Host *
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
AddKeysToAgent yes
|
||||||
|
ServerAliveInterval 60
|
||||||
|
ServerAliveCountMax 3
|
||||||
|
|
||||||
|
# Admin access to servers (use sma user)
|
||||||
|
Host admin-* *.admin
|
||||||
|
User sma
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_admin
|
||||||
|
|
||||||
|
# Git services (use geir user with dev key)
|
||||||
|
Host git.* github.com gitlab.com
|
||||||
|
User git
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
|
||||||
|
# Home lab servers (geir user for development access)
|
||||||
|
Host sleeper-service sleeper-service.home 10.0.0.8
|
||||||
|
User geir
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
|
||||||
|
Host grey-area grey-area.home 10.0.0.11
|
||||||
|
User geir
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
|
||||||
|
Host reverse-proxy reverse-proxy.home 10.0.0.12
|
||||||
|
User geir
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
|
||||||
|
# Admin access to servers (when needed)
|
||||||
|
Host admin-sleeper sleeper-service.admin
|
||||||
|
Hostname 10.0.0.8
|
||||||
|
User sma
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_admin
|
||||||
|
|
||||||
|
Host admin-grey grey-area.admin
|
||||||
|
Hostname 10.0.0.11
|
||||||
|
User sma
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_admin
|
||||||
|
|
||||||
|
Host admin-reverse reverse-proxy.admin
|
||||||
|
Hostname 10.0.0.12
|
||||||
|
User sma
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_admin
|
||||||
|
|
||||||
|
# Tailscale network
|
||||||
|
Host 100.* *.tail*
|
||||||
|
User geir
|
||||||
|
IdentityFile ~/.ssh/id_ed25519_dev
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
}
|
|
@ -21,6 +21,12 @@
|
||||||
|
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
|
|
||||||
|
# SSH access with development keys
|
||||||
|
openssh.authorizedKeys.keys = config.security.ssh-keys.development or [
|
||||||
|
# Fallback to current key during transition
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHeOvTHIw+hZOAiWkIrz9t11UeGwxAMx7jN/1IIdgq7O geokkjer@gmail.com"
|
||||||
|
];
|
||||||
|
|
||||||
# User-specific packages
|
# User-specific packages
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
# Browsers & Communication
|
# Browsers & Communication
|
||||||
|
|
|
@ -22,9 +22,8 @@
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
|
|
||||||
# SSH key-based authentication only (no password login)
|
# SSH key-based authentication only (no password login)
|
||||||
openssh.authorizedKeys.keys = [
|
openssh.authorizedKeys.keys = config.security.ssh-keys.admin or [
|
||||||
# Add SSH public key here when ready
|
# Admin keys will be populated from security module
|
||||||
# "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5... sma@home-lab"
|
|
||||||
];
|
];
|
||||||
|
|
||||||
# Essential admin packages
|
# Essential admin packages
|
||||||
|
|
24
plan.md
24
plan.md
|
@ -266,18 +266,19 @@ Home-lab/
|
||||||
- **10.0.0.8**: sleeper-service (Intel Xeon file server - rename from files.home)
|
- **10.0.0.8**: sleeper-service (Intel Xeon file server - rename from files.home)
|
||||||
- **10.0.0.11**: grey-area (planned application server)
|
- **10.0.0.11**: grey-area (planned application server)
|
||||||
- **10.0.0.12**: reverse-proxy (planned edge server)
|
- **10.0.0.12**: reverse-proxy (planned edge server)
|
||||||
- **10.0.0.14**: pi.hole (Pi-hole DNS/ad-blocker)
|
- **10.0.0.14**: pi.hole (Pi-hole DNS/ad-blocker) maybe move to nixos
|
||||||
- **10.0.0.90**: wordpresserver.home (existing WordPress server)
|
- **10.0.0.90**: wordpresserver.home (existing WordPress server) to be deleted, incus container
|
||||||
- **10.0.0.117**: webdev.home (existing web development server)
|
- **10.0.0.117**: webdev.home (existing web development server) to be deleted, incus container
|
||||||
- **10.0.0.138**: lan.home (router/gateway)
|
- **10.0.0.138**: lan.home (router/gateway/dhcp)
|
||||||
- **Tailscale Network (100.x.x.x/10)**:
|
- **Tailscale Network (100.x.x.x/10)**:
|
||||||
- **100.109.28.53**: congenital-optimist (current machine)
|
- **100.109.28.53**: congenital-optimist (current machine)
|
||||||
- **100.119.86.92**: apps (active server) (rename to grey area)
|
- **100.119.86.92**: apps (active server) (rename to grey area)
|
||||||
- **100.114.185.71**: arlaptop (laptop) (Arch Linux with plans to migrate to NixOS)
|
- **100.114.185.71**: arlaptop (laptop) (Arch Linux with plans to migrate to NixOS)
|
||||||
- **100.81.15.84**: files (file server)
|
- **100.81.15.84**: files (file server rename to sleeper-service )
|
||||||
- **100.103.143.108**: pihole (DNS server)
|
- **100.103.143.108**: pihole (DNS server)
|
||||||
- **100.96.189.104**: vps1 (external VPS) (rename to reverse proxy)
|
- **100.96.189.104**: vps1 (external VPS) (rename to reverse proxy)
|
||||||
- **100.126.202.40**: wordpresserver (WordPress)
|
- **100.126.202.40**: wordpresserver (WordPress) to be deleted
|
||||||
|
- remind user to update tailsce or find a way to use the cli to do this
|
||||||
- [ ] **VLAN planning**: Consider network segmentation for different service types
|
- [ ] **VLAN planning**: Consider network segmentation for different service types
|
||||||
- [ ] **DNS configuration**: Plan local DNS resolution for internal services
|
- [ ] **DNS configuration**: Plan local DNS resolution for internal services
|
||||||
|
|
||||||
|
@ -377,9 +378,18 @@ Home-lab/
|
||||||
|
|
||||||
### 5.3 Security & Networking
|
### 5.3 Security & Networking
|
||||||
- [x] **systemd-networkd migration**: Completed for sleeper-service with static IP configuration
|
- [x] **systemd-networkd migration**: Completed for sleeper-service with static IP configuration
|
||||||
|
- [x] **SSH key management centralization**: Implemented two-key strategy
|
||||||
|
- **Admin key** (`geir@geokkjer.eu-admin`): For sma user, server administration access
|
||||||
|
- **Development key** (`geir@geokkjer.eu-dev`): For geir user, git services, daily development
|
||||||
|
- **NixOS module**: `modules/security/ssh-keys.nix` centralizes key management
|
||||||
|
- **SSH client config**: Updated with role-based host patterns and key selection
|
||||||
|
- **Security benefits**: Principle of least privilege, limited blast radius if compromised
|
||||||
|
- **Usage examples**:
|
||||||
|
- `ssh geir@sleeper-service.home` - Uses dev key automatically
|
||||||
|
- `ssh admin-sleeper` - Uses admin key for sma user access
|
||||||
|
- `git clone git@github.com:user/repo` - Uses dev key for git operations
|
||||||
- [ ] VPN configuration (Tailscale expansion)
|
- [ ] VPN configuration (Tailscale expansion)
|
||||||
- [ ] Firewall rules standardization across machines
|
- [ ] Firewall rules standardization across machines
|
||||||
- [ ] SSH key management centralization
|
|
||||||
- [ ] Certificate management (Let's Encrypt)
|
- [ ] Certificate management (Let's Encrypt)
|
||||||
- [ ] Network segmentation planning (VLANs for services vs. user devices)
|
- [ ] Network segmentation planning (VLANs for services vs. user devices)
|
||||||
- [ ] DNS infrastructure (local DNS server for service discovery)
|
- [ ] DNS infrastructure (local DNS server for service discovery)
|
||||||
|
|
89
scripts/setup-ssh-keys.sh
Executable file
89
scripts/setup-ssh-keys.sh
Executable file
|
@ -0,0 +1,89 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# SSH Key Generation Script - Two-Key Strategy
|
||||||
|
# Generates admin and development SSH keys
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SSH_DIR="$HOME/.ssh"
|
||||||
|
HOSTNAME="$(hostname)"
|
||||||
|
EMAIL_BASE="geir@geokkjer.eu"
|
||||||
|
|
||||||
|
echo "🔑 Setting up SSH keys for $HOSTNAME"
|
||||||
|
echo "📧 Using email base: $EMAIL_BASE"
|
||||||
|
|
||||||
|
# Create SSH directory if it doesn't exist
|
||||||
|
mkdir -p "$SSH_DIR"
|
||||||
|
chmod 700 "$SSH_DIR"
|
||||||
|
|
||||||
|
# Backup existing key if it exists
|
||||||
|
if [[ -f "$SSH_DIR/id_ed25519" ]]; then
|
||||||
|
echo "💾 Backing up existing key to id_ed25519.backup"
|
||||||
|
cp "$SSH_DIR/id_ed25519" "$SSH_DIR/id_ed25519.backup"
|
||||||
|
cp "$SSH_DIR/id_ed25519.pub" "$SSH_DIR/id_ed25519.pub.backup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔐 Generating two SSH keys:"
|
||||||
|
echo " 1. Admin key (for sma user, server administration)"
|
||||||
|
echo " 2. Development key (for geir user, git, daily use)"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Generate admin key
|
||||||
|
ADMIN_KEY="$SSH_DIR/id_ed25519_admin"
|
||||||
|
if [[ ! -f "$ADMIN_KEY" ]]; then
|
||||||
|
echo "🔐 Generating admin key..."
|
||||||
|
ssh-keygen -t ed25519 -f "$ADMIN_KEY" -C "$EMAIL_BASE-admin" -N ""
|
||||||
|
chmod 600 "$ADMIN_KEY"
|
||||||
|
chmod 644 "$ADMIN_KEY.pub"
|
||||||
|
echo "✅ Generated: $ADMIN_KEY"
|
||||||
|
else
|
||||||
|
echo "⏭️ Admin key already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate development key
|
||||||
|
DEV_KEY="$SSH_DIR/id_ed25519_dev"
|
||||||
|
if [[ ! -f "$DEV_KEY" ]]; then
|
||||||
|
echo "🔐 Generating development key..."
|
||||||
|
ssh-keygen -t ed25519 -f "$DEV_KEY" -C "$EMAIL_BASE-dev" -N ""
|
||||||
|
chmod 600 "$DEV_KEY"
|
||||||
|
chmod 644 "$DEV_KEY.pub"
|
||||||
|
echo "✅ Generated: $DEV_KEY"
|
||||||
|
else
|
||||||
|
echo "⏭️ Development key already exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🎯 Next steps:"
|
||||||
|
echo "1. Add these public keys to your NixOS configuration:"
|
||||||
|
echo "2. Deploy updated configuration to target servers"
|
||||||
|
echo "3. Test SSH access with both keys"
|
||||||
|
echo "4. Update external Git services with new development key"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "📋 Public keys to add to NixOS configuration:"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
if [[ -f "$ADMIN_KEY.pub" ]]; then
|
||||||
|
echo "# Admin key (add to security.ssh-keys.admin in modules/security/ssh-keys.nix)"
|
||||||
|
echo "\"$(cat "$ADMIN_KEY.pub")\""
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f "$DEV_KEY.pub" ]]; then
|
||||||
|
echo "# Development key (add to security.ssh-keys.development in modules/security/ssh-keys.nix)"
|
||||||
|
echo "\"$(cat "$DEV_KEY.pub")\""
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "💡 Usage examples:"
|
||||||
|
echo " ssh geir@sleeper-service.home # Uses dev key automatically"
|
||||||
|
echo " ssh admin-sleeper # Uses admin key for sma user"
|
||||||
|
echo " git clone git@github.com:user/repo # Uses dev key for git"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "🔄 To update your Git remotes with the new key:"
|
||||||
|
echo " # Add new key to GitHub/GitLab first, then:"
|
||||||
|
echo " ssh -T git@github.com # Test the connection"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "✅ SSH key setup complete!"
|
Loading…
Add table
Add a link
Reference in a new issue