Initial commit
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# SOPS age key
|
||||
age.key
|
||||
|
||||
# Encrypted secrets (plaintext versions)
|
||||
*.yaml.unencrypted
|
||||
*.yaml.decrypted
|
||||
|
||||
# Nix build artifacts
|
||||
/nix/
|
||||
/result/
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.swp
|
||||
|
||||
# IDE/Editor files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
|
||||
# OS-specific files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
8
.sops.yaml
Normal file
8
.sops.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# sops configuration
|
||||
# This file tells SOPS how to decrypt your secrets
|
||||
# It will be used by both the sops CLI and sops-nix
|
||||
|
||||
creation_rules:
|
||||
- path_regex: hosts/[^/]+/secrets\.yaml$
|
||||
age: age1t9c8j4yclx7wylzry8k0f473p4qt32d0kvgj8ce5k5zqvj2p9g4qsplaw8
|
||||
27
Dockerfile
Normal file
27
Dockerfile
Normal file
@@ -0,0 +1,27 @@
|
||||
FROM nixos/nix:latest
|
||||
|
||||
# Install dependencies
|
||||
RUN nix-env -iA nixpkgs.colmena nixpkgs.sops nixpkgs.age nixpkgs.yq nixpkgs.jq nixpkgs TMPEXIT=0
|
||||
|
||||
# Create directories
|
||||
RUN mkdir -p /workspace /etc/sops/keys
|
||||
|
||||
# Copy files at build time (these will be part of the image)
|
||||
COPY . /workspace/
|
||||
COPY age.key /etc/sops/keys/age.key
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /workspace
|
||||
|
||||
# Set environment variables
|
||||
ENV NIX_CONFIG_DIR=/root/.config/nix
|
||||
ENV SOPS_AGE_KEY_FILE=/etc/sops/keys/age.key
|
||||
|
||||
# Create nix.conf
|
||||
RUN mkdir -p /root/.config/nix && \
|
||||
echo "experimental-features = nix-command flakes" > /root/.config/nix/nix.conf
|
||||
|
||||
# Make age.key readable
|
||||
RUN chmod 600 /etc/sops/keys/age.key
|
||||
|
||||
CMD ["bash"]
|
||||
5
Readme.md
Normal file
5
Readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Note; you are running on a windows host, so your going to need to work around that for configuring nixos
|
||||
|
||||
# Tasks:
|
||||
- Cleanup the repo for nixos as this is a fresh nixos setup, ive already provided the initial machien as hosts\blade
|
||||
- Setup colmena for this nixos
|
||||
244
Taskfile.yml
Normal file
244
Taskfile.yml
Normal file
@@ -0,0 +1,244 @@
|
||||
# ------------------------------------------------------------
|
||||
# Taskfile – Docker‑based Nix development & Colmena deployment
|
||||
# ------------------------------------------------------------
|
||||
version: "3"
|
||||
|
||||
vars:
|
||||
# Base directory of the repository – pass it when you invoke `task`,
|
||||
# e.g. `task -v ROOT_DIR=$(pwd) …`. You can also export it in your shell.
|
||||
ROOT_DIR: "{{ .ROOT_DIR }}"
|
||||
|
||||
# Convenience paths (expanded by `task` before being passed to Docker)
|
||||
FLAKE_DIR: "{{ .ROOT_DIR }}"
|
||||
AGE_KEY_PATH: "{{ .ROOT_DIR }}/age.key"
|
||||
SECRETS_YAML_PATH: "{{ .ROOT_DIR }}/hosts/blade/secrets.yaml"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Docker helpers (the Nix container always gets the repo mounted at
|
||||
# /workspace). `DOCKER_NIX_CMD` is used for *any* command that runs
|
||||
# inside the container.
|
||||
# -----------------------------------------------------------------
|
||||
DOCKER_COMPOSE_CMD: "docker compose -f {{ .ROOT_DIR }}/docker-compose.yml"
|
||||
DOCKER_NIX_CMD: >-
|
||||
{{ .DOCKER_COMPOSE_CMD }} run --rm
|
||||
-v "{{ .ROOT_DIR }}:/workspace"
|
||||
nixos
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Docker management
|
||||
# -----------------------------------------------------------------
|
||||
tasks:
|
||||
docker-build:
|
||||
desc: Build the Docker container for Nix
|
||||
cmds:
|
||||
- "{{ .DOCKER_COMPOSE_CMD }} build"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# ---------------------------------------------------------------
|
||||
# NOTE: we now use DOCKER_NIX_CMD (which already has the bind‑mount)
|
||||
# ---------------------------------------------------------------
|
||||
docker-shell:
|
||||
desc: Enter a shell in the Docker container (repo is mounted)
|
||||
cmds:
|
||||
- "{{ .DOCKER_NIX_CMD }} bash"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
docker-up:
|
||||
desc: Start the Docker container (detached)
|
||||
cmds:
|
||||
- "{{ .DOCKER_COMPOSE_CMD }} up -d"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
docker-down:
|
||||
desc: Stop the Docker container
|
||||
cmds:
|
||||
- "{{ .DOCKER_COMPOSE_CMD }} down"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Age‑key handling (SOPS)
|
||||
# -----------------------------------------------------------------
|
||||
generate-age-key:
|
||||
desc: Generate a new age key for a host (default - all hosts without a key)
|
||||
vars:
|
||||
# If HOST is supplied we generate only for that host; otherwise we
|
||||
# iterate over every directory under `hosts/` that lacks an age.key.
|
||||
TARGET_HOSTS: |
|
||||
{{- if .HOST -}}
|
||||
{{ .HOST }}
|
||||
{{- else -}}
|
||||
{{- range $dir := (files (printf "%s/hosts/*" .ROOT_DIR)) -}}
|
||||
{{- $name := base $dir -}}
|
||||
{{- if not (fileExists (printf "%s/age.key" $dir)) -}}
|
||||
{{ $name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
cmds:
|
||||
- |
|
||||
{{- $list := splitList "\n" .TARGET_HOSTS -}}
|
||||
{{- range $h := $list }}
|
||||
echo "🔑 Generating age.key for host '{{ $h }}' ..."
|
||||
{{ .DOCKER_NIX_CMD }} -v "{{ .ROOT_DIR }}/hosts/{{ $h }}:/workspace/hosts/{{ $h }}" \
|
||||
nixos age-keygen -o /workspace/hosts/{{ $h }}/age.key
|
||||
{{- end }}
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Encrypt / Decrypt (loop over hosts)
|
||||
# -----------------------------------------------------------------
|
||||
encrypt-secrets:
|
||||
desc: |
|
||||
Encrypt `secrets.yaml` for every host that has an age.key.
|
||||
Pass HOST=<name> to limit to a single host.
|
||||
vars:
|
||||
# Space‑separated list of hosts that have both age.key & secrets.yaml
|
||||
TARGET_HOSTS: |
|
||||
{{- if .HOST -}}
|
||||
{{ .HOST }}
|
||||
{{- else -}}
|
||||
{{- $list := slice -}}
|
||||
{{- range $dir := (files (printf "%s/hosts/*" .ROOT_DIR)) -}}
|
||||
{{- $name := base $dir -}}
|
||||
{{- $age := printf "%s/age.key" $dir -}}
|
||||
{{- $sec := printf "%s/secrets.yaml" $dir -}}
|
||||
{{- if (and (fileExists $age) (fileExists $sec)) -}}
|
||||
{{- $list = append $list $name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- join " " $list -}}
|
||||
{{- end }}
|
||||
preconditions:
|
||||
- sh: test -n "{{ .TARGET_HOSTS }}"
|
||||
msg: "No hosts with both age.key and secrets.yaml were found."
|
||||
cmds:
|
||||
- |
|
||||
for host in {{ .TARGET_HOSTS }}; do
|
||||
echo "🔐 Encrypting secrets for host '$host' ..."
|
||||
{{ .DOCKER_NIX_CMD }} -v "{{ .ROOT_DIR }}/hosts/$host:/workspace/hosts/$host" \
|
||||
nixos sh -c "\
|
||||
pub=\$(grep 'public key' /workspace/hosts/$host/age.key | awk '{print \$NF}') && \
|
||||
sops --encrypt --age=\$pub --in-place /workspace/hosts/$host/secrets.yaml"
|
||||
done
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
decrypt-secrets:
|
||||
desc: |
|
||||
Decrypt `secrets.yaml` for every host that has an age.key.
|
||||
Decrypted output is written to `secrets.yaml.decrypted`.
|
||||
Pass HOST=<name> to limit to a single host.
|
||||
vars:
|
||||
TARGET_HOSTS: |
|
||||
{{- if .HOST -}}
|
||||
{{ .HOST }}
|
||||
{{- else -}}
|
||||
{{- $list := slice -}}
|
||||
{{- range $dir := (files (printf "%s/hosts/*" .ROOT_DIR)) -}}
|
||||
{{- $name := base $dir -}}
|
||||
{{- $age := printf "%s/age.key" $dir -}}
|
||||
{{- $sec := printf "%s/secrets.yaml" $dir -}}
|
||||
{{- if (and (fileExists $age) (fileExists $sec)) -}}
|
||||
{{- $list = append $list $name -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- join " " $list -}}
|
||||
{{- end }}
|
||||
preconditions:
|
||||
- sh: test -n "{{ .TARGET_HOSTS }}"
|
||||
msg: "No hosts with both age.key and secrets.yaml were found."
|
||||
cmds:
|
||||
- |
|
||||
for host in {{ .TARGET_HOSTS }}; do
|
||||
echo "🔓 Decrypting secrets for host '$host' ..."
|
||||
{{ .DOCKER_NIX_CMD }} -v "{{ .ROOT_DIR }}/hosts/$host:/workspace/hosts/$host" \
|
||||
nixos sh -c "\
|
||||
pub=\$(grep '# public key' /workspace/hosts/$host/age.key | awk '{print \$NF}') && \
|
||||
sops --decrypt --age=\$pub /workspace/hosts/$host/secrets.yaml \
|
||||
> /workspace/hosts/$host/secrets.yaml.decrypted"
|
||||
done
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Nix flake & build
|
||||
# -----------------------------------------------------------------
|
||||
flake-check:
|
||||
desc: Run `nix flake check` on the repository
|
||||
cmds:
|
||||
- "{{ .DOCKER_NIX_CMD }} nix flake check --flake /workspace"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
build-blade:
|
||||
desc: Build the NixOS configuration for the *blade* host
|
||||
cmds:
|
||||
- "{{ .DOCKER_NIX_CMD }} nix build /workspace#nixosConfigurations.blade"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Colmena deployment
|
||||
# -----------------------------------------------------------------
|
||||
deploy:
|
||||
desc: Deploy to an arbitrary node (usage - task deploy NODE=blade)
|
||||
cmds:
|
||||
- "{{ .DOCKER_NIX_CMD }} colmena apply --on {{ .NODE }}"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
preconditions:
|
||||
- sh: test -n "{{ .NODE }}"
|
||||
msg: "NODE variable is required. Example: task deploy NODE=blade"
|
||||
- sh: test -f "{{ .ROOT_DIR }}/age.key"
|
||||
- sh: test -f "{{ .ROOT_DIR }}/hosts/{{ .NODE }}/secrets.yaml"
|
||||
|
||||
deploy-blade:
|
||||
desc: Deploy the configuration to the *blade* host
|
||||
cmds:
|
||||
- "{{ .DOCKER_NIX_CMD }} colmena apply --on blade"
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
preconditions:
|
||||
- sh: test -f "{{ .ROOT_DIR }}/age.key"
|
||||
- sh: test -f "{{ .ROOT_DIR }}/hosts/blade/secrets.yaml"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# Helper: add a new node
|
||||
# -----------------------------------------------------------------
|
||||
add-node:
|
||||
desc: Create a new host directory with skeleton Nix files
|
||||
prompt: "Enter the name of the new node (e.g., node2):"
|
||||
cmds:
|
||||
- mkdir -p "{{ .FLAKE_DIR }}/hosts/{{ .CLI_ARGS }}"
|
||||
- |
|
||||
cat > "{{ .FLAKE_DIR }}/hosts/{{ .CLI_ARGS }}/configuration.nix" <<'EOF'
|
||||
{ config, lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
../../common.nix
|
||||
];
|
||||
networking.hostName = "{{ .CLI_ARGS }}";
|
||||
}
|
||||
EOF
|
||||
- |
|
||||
cat > "{{ .FLAKE_DIR }}/hosts/{{ .CLI_ARGS }}/hardware-configuration.nix" <<'EOF'
|
||||
# Add hardware‑specific configurations here
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
{
|
||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
||||
}
|
||||
EOF
|
||||
- |
|
||||
cat > "{{ .FLAKE_DIR }}/hosts/{{ .CLI_ARGS }}/secrets.yaml" <<'EOF'
|
||||
# Add node‑specific secrets here
|
||||
EOF
|
||||
- |
|
||||
cat > "{{ .FLAKE_DIR }}/hosts/{{ .CLI_ARGS }}/default.nix" <<'EOF'
|
||||
{ ... }: { imports = [ ./configuration.nix ./hardware-configuration.nix ../../common.nix ]; }
|
||||
EOF
|
||||
dir: "{{ .ROOT_DIR }}"
|
||||
|
||||
# -----------------------------------------------------------------
|
||||
# House‑keeping
|
||||
# -----------------------------------------------------------------
|
||||
clean:
|
||||
desc: Remove temporary/decrypted secret files for all hosts
|
||||
cmds:
|
||||
- |
|
||||
find "{{ .ROOT_DIR }}/hosts" -name 'secrets.yaml.decrypted' -delete
|
||||
silent: true
|
||||
39
common.nix
Normal file
39
common.nix
Normal file
@@ -0,0 +1,39 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Shared users
|
||||
users.mutableUsers = false;
|
||||
users.users.phoenix = {
|
||||
isNormalUser = true;
|
||||
description = "Phoenix";
|
||||
extraGroups = [ "wheel" ];
|
||||
shell = pkgs.bash;
|
||||
home = "/home/phoenix";
|
||||
createHome = true;
|
||||
useDefaultShell = true;
|
||||
};
|
||||
|
||||
# Shared packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
nano
|
||||
vim
|
||||
git
|
||||
curl
|
||||
wget
|
||||
sops
|
||||
age
|
||||
];
|
||||
|
||||
# Shared services
|
||||
services.openssh.enable = true;
|
||||
services.openssh.permitRootLogin = "no";
|
||||
|
||||
# Timezone and locale
|
||||
time.timeZone = "Europe/London";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
console.keyMap = "uk";
|
||||
|
||||
# Firewall
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowedTCPPorts = [ 22 ]; # SSH
|
||||
}
|
||||
28
docker-compose.yml
Normal file
28
docker-compose.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
services:
|
||||
nixos:
|
||||
image: nixos-builder:latest
|
||||
container_name: nixos-builder
|
||||
volumes:
|
||||
- .:/workspace
|
||||
- ./age.key:/etc/sops/keys/age.key:ro
|
||||
- nix_store:/nix
|
||||
- nix_cache:/root/.cache/nix
|
||||
environment:
|
||||
- NIX_CONFIG_DIR=/root/.config/nix
|
||||
- SOPS_AGE_KEY_FILE=/etc/sops/keys/age.key
|
||||
- TMPDIR=/tmp
|
||||
tmpfs:
|
||||
- /tmp
|
||||
working_dir: /workspace
|
||||
tty: true
|
||||
stdin_open: true
|
||||
profiles:
|
||||
- default
|
||||
security_opt:
|
||||
- apparmor:unconfined
|
||||
cap_add:
|
||||
- SYS_ADMIN
|
||||
|
||||
volumes:
|
||||
nix_store:
|
||||
nix_cache:
|
||||
151
flake.lock
generated
Normal file
151
flake.lock
generated
Normal file
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"nodes": {
|
||||
"colmena": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"flake-utils": "flake-utils",
|
||||
"nix-github-actions": "nix-github-actions",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"stable": "stable"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1762034856,
|
||||
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "zhaofengli",
|
||||
"repo": "colmena",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1650374568,
|
||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1659877975,
|
||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"colmena",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1729742964,
|
||||
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1750134718,
|
||||
"narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-stable": {
|
||||
"locked": {
|
||||
"lastModified": 1688392541,
|
||||
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-22.11",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1779560665,
|
||||
"narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"colmena": "colmena",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-stable": "nixpkgs-stable"
|
||||
}
|
||||
},
|
||||
"stable": {
|
||||
"locked": {
|
||||
"lastModified": 1750133334,
|
||||
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-25.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
28
flake.nix
Normal file
28
flake.nix
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
description = "Colmena Remote NixOS Management";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-22.11";
|
||||
|
||||
colmena.url = "github:zhaofengli/colmena";
|
||||
};
|
||||
|
||||
outputs = inputs@{ nixpkgs, colmena, ... }:
|
||||
{
|
||||
colmena = {
|
||||
meta = {
|
||||
nixpkgs = import nixpkgs {
|
||||
system = "x86_64-linux";
|
||||
overlays = [];
|
||||
};
|
||||
|
||||
specialArgs = {
|
||||
inherit inputs;
|
||||
};
|
||||
};
|
||||
|
||||
blade = import ./hosts/blade;
|
||||
};
|
||||
};
|
||||
}
|
||||
96
hosts/blade/default.nix
Normal file
96
hosts/blade/default.nix
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
name,
|
||||
nodes,
|
||||
pkgs,
|
||||
lib,
|
||||
inputs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
|
||||
deployment = {
|
||||
targetHost = "192.168.1.69"; # also supports an IP address
|
||||
targetPort = 22;
|
||||
targetUser = "phoenix";
|
||||
buildOnTarget = true;
|
||||
keys.phoenix.keyFile = "/home/nixos/.ssh/id_ed25519.pub";
|
||||
};
|
||||
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# boot.loader.grub.enable = true;
|
||||
networking.useDHCP = false;
|
||||
networking.interfaces.eth0.useDHCP = true;
|
||||
time.timeZone = "America/New_York";
|
||||
networking.hostName = "blade";
|
||||
services.xserver.xkb.layout = "uk";
|
||||
i18n.defaultLocale = "en_US.UTF-8";
|
||||
|
||||
nix.settings.trusted-users = [
|
||||
"root"
|
||||
"@wheel"
|
||||
];
|
||||
|
||||
users.users.phoenix = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"networkmanager"
|
||||
];
|
||||
home = "/home/phoenix";
|
||||
packages = with pkgs; [
|
||||
vim
|
||||
tree
|
||||
lego
|
||||
];
|
||||
openssh.authorizedKeys.keys = [
|
||||
"sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBMPNyAyMrqlI3tUI39TqcgYBciIC+aY2UNAunFqylhhzTVA14rluMjFqHf9HKs9SHZ52nLEV58/BxlnMeMtRc+cAAAAEc3NoOg== phoenix@DESKTOP-1A9MAJO"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMoM3FANeYtWLJIiTL+nU0XzZft2psiSgbCmNfQZBXgy nixos@nixos"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.user.services.dbus = {
|
||||
restartIfChanged = false;
|
||||
};
|
||||
|
||||
security.sudo.extraRules = [
|
||||
{
|
||||
users = [ "phoenix" ];
|
||||
commands = [
|
||||
{
|
||||
command = "ALL";
|
||||
options = [ "NOPASSWD" ]; # "SETENV" # Adding the following could be a good idea
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
inetutils
|
||||
mtr
|
||||
sysstat
|
||||
dig
|
||||
openssl
|
||||
];
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
settings.PermitRootLogin = "yes";
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [
|
||||
22
|
||||
80
|
||||
443
|
||||
];
|
||||
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||
networking.firewall.enable = true;
|
||||
networking.usePredictableInterfaceNames = false;
|
||||
# Bootloader
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
}
|
||||
31
hosts/blade/hardware-configuration.nix
Normal file
31
hosts/blade/hardware-configuration.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "uas" "usb_storage" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-intel" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-uuid/64882a2d-c966-4fc9-96f0-413c6d835848";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
fileSystems."/boot" =
|
||||
{ device = "/dev/disk/by-uuid/8381-A6DD";
|
||||
fsType = "vfat";
|
||||
options = [ "fmask=0022" "dmask=0022" ];
|
||||
};
|
||||
|
||||
swapDevices = [ ];
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
|
||||
}
|
||||
17
hosts/blade/secrets.yaml
Normal file
17
hosts/blade/secrets.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
phoenix_password: ENC[AES256_GCM,data:v39j4NSTWfDcg1em5eat7APzEAOdgxWZ7RVhtErVFfVsvK7lof3mmdjfcqaRiJL0VZunY6/idAIG9m18p6+14+pre3Esrr56iw==,iv:ut2M0g+tgVwNA2MGb0OhQRLevcQp8IkkYvnJlDzIK3Q=,tag:AtL7MAntOPSp37T+12jy3A==,type:str]
|
||||
root_password: ENC[AES256_GCM,data:qn/nJm1Wt9GPVh1qifIIxOp89WWGMuAL52JHoHC3S+0HHFkAds+ZuvuXWnwt6t9WG3v8QdBXbGEK+KlEwdyke5OTfnWQXr0udA==,iv:Ve1IAI3vRGnUSgJoSYKGl3swLKjgozFL5I7crbAjtWw=,tag:6IBWbriKr1bt0IWuppLlRg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age1t9c8j4yclx7wylzry8k0f473p4qt32d0kvgj8ce5k5zqvj2p9g4qsplaw8
|
||||
enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQL0lPQWh1ME5Ibm1vSnF6
|
||||
WHg5VDZGaEt2bVFMN2tVUm9rbjNBVTdNdWo0Ck9aeVI2NVpDR3l3Qk5GTE1EN0I0
|
||||
L2JtLzg3aFJqaEpURWs4cy9iZWNVNEkKLS0tIHhnUEdQVm5odk04QjJLKzNPdnU4
|
||||
MVpEejNnN0xNYWRxeVFLV2c5MTBhbmMKi4y6u2MaqjnnNR/jKXPZDBX2xfnkbwZ3
|
||||
ZP/Eu4qwakyow6pmn0Xw4IMizkAmylQWQL7T2lfoqatZ2sAyUQj2Yg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2026-05-28T14:31:52Z"
|
||||
mac: ENC[AES256_GCM,data:dzNPYMmmDV4VjFeGa0FtcPbGQmVo48V7M8kqnmH4HsZJRUlBO+sNclQbBibGjne5hZYP6h2dfRb3gXYV4OmmLUcaQenMRLAUGQvR80wAIRFcD+v7ax2oqiG0sTkodtG8dFfeKwpWvWLTL6IuVuEZ0+yVp9pvtqHPdrB0c73rqzY=,iv:T6d4B4s0OY/InJ03y4COPG0Ms0WlwN1WQjK+lThnjzM=,tag:Jni2/94F+SX1149/cBK2dA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
Reference in New Issue
Block a user