playbook base initial skeleton

This commit is contained in:
m3tam3re 2025-03-12 14:28:01 +01:00
commit b97263495b
14 changed files with 471 additions and 0 deletions

44
flake.lock generated Normal file
View File

@ -0,0 +1,44 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1741600792,
"narHash": "sha256-yfDy6chHcM7pXpMF4wycuuV+ILSTG486Z/vLx/Bdi6Y=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ebe2788eafd539477f83775ef93c3c7e244421d3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1741708242,
"narHash": "sha256-cNRqdQD4sZpN7JLqxVOze4+WsWTmv2DGH0wNCOVwrWc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b62d2a95c72fb068aecd374a7262b37ed92df82b",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b62d2a95c72fb068aecd374a7262b37ed92df82b",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs",
"nixpkgs-unstable": "nixpkgs-unstable"
}
}
},
"root": "root",
"version": 7
}

39
flake.nix Normal file
View File

@ -0,0 +1,39 @@
# self-host-playbook-base/flake.nix
{
description = "Base configuration for self-host-playbook";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/b62d2a95c72fb068aecd374a7262b37ed92df82b";
};
outputs = {
self,
nixpkgs,
nixpkgs-unstable,
}: {
nixosModules = {
default = {tier ? "starter"}: {
config,
lib,
pkgs,
...
}: {
nixpkgs.overlays = [
(final: _prev: {
unstable = import nixpkgs-unstable {
system = final.system;
};
})
];
imports = [
./modules/core.nix
(import ./modules/services.nix {
inherit lib config pkgs;
tier = tier;
})
];
};
};
};
}

69
justfiles/main.just Normal file
View File

@ -0,0 +1,69 @@
import? "/etc/self-host-playbook/tiers/core.just"
import? "/etc/self-host-playbook/tiers/starter.just"
import? "/etc/self-host-playbook/tiers/premium.just"
@default:
#!/usr/bin/env bash
# Function to show the header
show_header() {
gum style \
--foreground 212 --border double --border-foreground 212 \
--align center --width 50 --margin "1 2" --padding "1 2" \
"🚀 DevOps Control Center 🚀"
}
# Function to create menu items with icons and descriptions
create_menu() {
echo "📊 Status - Show running docker containers"
echo "📝 Logs - View container logs"
echo "💾 Disk Usage - Show docker disk usage"
echo "🔄 Restart - Restart a specific container"
echo "🐳 Update Docker - Update Docker containers"
echo "❌ Exit"
}
while true; do
clear
show_header
# Show menu and get selection
choice=$(create_menu | gum choose --cursor.foreground 212 --selected.foreground 212 --header "Select an action:" --cursor "➜ ")
# Exit if no selection
if [ -z "$choice" ]; then
exit 0
fi
# Process selection
case $choice in
"📊 Status"*)
just status
;;
"📝 Logs"*)
just logs
;;
"🛑 Stop All"*)
just docker-stop-all
;;
"🗑️ Prune"*)
just docker-prune
;;
"💾 Disk Usage"*)
just docker-disk
;;
"🔄 Restart"*)
just docker-restart
;;
"🐳 Update Docker"*)
just update-containers
;;
"❌ Exit")
echo "Goodbye! 👋" | gum style --foreground 212
exit 0
;;
esac
# Pause after command execution
gum confirm "Press Enter to continue..." --default=true --affirmative "Continue" --negative "Exit" || exit 0
done

101
justfiles/tiers/core.just Normal file
View File

@ -0,0 +1,101 @@
status:
#!/usr/bin/env bash
gum style --foreground 212 --bold --border normal --align center --width 50 --margin "1 2" "📊 Running Containers"
docker ps --format "table {{"{{.Names}}\t{{.Status}}"}}" | gum table
# Interactive logs viewer with gum
logs:
#!/usr/bin/env bash
gum style --foreground 212 --bold --border normal --align center --width 50 --margin "1 2" "📝 Docker Logs Viewer"
# Get running container names
containers=($(docker ps --format "{{"{{.Names}}"}}"))
if [ ${#containers[@]} -eq 0 ]; then
gum style --foreground 1 "⚠️ No running containers found"
exit 1
fi
# Select container using gum choose
container=$(printf "%s\n" "${containers[@]}" | gum choose --header "Select a container:" --cursor.foreground 212)
if [ -z "$container" ]; then
exit 0
fi
# Select number of lines using gum choose
lines=$(gum choose --header "Select number of log lines:" --cursor.foreground 212 \
"5 lines" "10 lines" "25 lines" "50 lines" "100 lines" "200 lines")
if [ -z "$lines" ]; then
exit 0
fi
# Extract number from selection
lines=${lines%% *}
# Show spinner while fetching logs
gum spin --spinner dot --title "Fetching logs..." -- sleep 1
# Show logs
docker logs "$container" 2>&1 | tail -n "$lines" | gum pager
docker-disk:
#!/usr/bin/env bash
gum style --foreground 212 --bold --border normal --align center --width 50 --margin "1 2" "💾 Docker Disk Usage"
docker system df | gum table
docker-restart:
#!/usr/bin/env bash
containers=($(docker ps --format "{{"{{.Names}}"}}"))
if [ ${#containers[@]} -eq 0 ]; then
gum style --foreground 1 "⚠️ No running containers found"
exit 1
fi
container=$(printf "%s\n" "${containers[@]}" | gum choose --header "Select a container to restart:" --cursor.foreground 212)
if [ -n "$container" ]; then
gum spin --spinner dot --title "Restarting $container..." -- docker restart "$container"
gum style --foreground 212 "✅ Container $container restarted successfully!"
fi
update-containers:
#!/usr/bin/env bash
set -e # Exit on error
CONTAINERS=($(docker ps --format "{{"{{.Names}}"}}"))
echo "Will update these containers:"
printf '%s\n' "${CONTAINERS[@]}" | gum table && \
gum confirm "Continue?" || exit 0
# First collect all image information
declare -A CONTAINER_IMAGES
echo "Collecting image information..."
for container in "${CONTAINERS[@]}"; do
FULL_IMAGE=$(docker inspect "$container" --format '{{"{{.Config.Image}}"}}')
CONTAINER_IMAGES[$container]=$(echo "$FULL_IMAGE" | sed 's/@sha256.*$//')
echo "$container -> ${CONTAINER_IMAGES[$container]}"
done
echo "Stopping containers..." && \
for container in "${CONTAINERS[@]}"; do
echo "Stopping $container..."
sudo systemctl stop "docker-$container.service"
done
echo "Pulling new images..." && \
for container in "${CONTAINERS[@]}"; do
IMAGE="${CONTAINER_IMAGES[$container]}"
echo -e "\n📥 Pulling $IMAGE for $container..." | gum style --foreground 99
if ! docker pull "$IMAGE" --quiet=false; then
echo "❌ Failed to pull $IMAGE" | gum style --foreground 196
exit 1
fi
echo "------------------------"
done
echo "Starting containers..." && \
for container in "${CONTAINERS[@]}"; do
echo "Starting $container..."
sudo systemctl start "docker-$container.service"
done && \
gum style --foreground 212 "✅ Containers updated successfully!"

View File

View File

95
modules/core.nix Normal file
View File

@ -0,0 +1,95 @@
{pkgs, ...}: {
imports = [
./hardware-configuration.nix
];
# Enable flakes and nix commands
nix = {
settings = {
experimental-features = ["nix-command" "flakes"];
# Enable automatic garbage collection
auto-optimise-store = true;
};
# Automatic cleanup of old generations
gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 30d";
};
};
# Boot configuration
boot.loader.grub = {
enable = true;
efiSupport = true;
efiInstallAsRemovable = true;
};
# Your base configuration here
system.autoUpgrade = {
enable = true;
allowReboot = true;
dates = "04:00";
flake = "path:/etc/nixos/current";
randomizedDelaySec = "45min";
flags = [
"--update-input nixpkgs"
"--update-input base-config"
];
};
# Other base configurations...
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
MaxAuthTries = 3;
LoginGraceTime = "30s";
};
ports = [2222];
};
# System packages
environment.systemPackages = with pkgs; [
# Docker tools
docker
docker-compose
# System utilities
neovim
git
unstable.gum
just
jq
(pkgs.writeShellScriptBin "shp" ''
exec sudo ${pkgs.just}/bin/just -f /etc/self-host-playbook/justfile "$@"
'')
];
# Enable Docker with recommended settings
virtualisation = {
docker = {
enable = true;
# Enable docker daemon to start on boot
enableOnBoot = true;
# Use overlay2 storage driver
storageDriver = "overlay2";
# Enable live restore
liveRestore = true;
};
oci-containers = {
backend = "docker";
};
};
environment.etc = {
# Main justfile
"self-host-playbook/justfile".source = ../justfiles/main.just;
# Tier justfiles
"self-host-playbook/tiers/core.just".source = ../justfiles/tiers/core.just;
"self-host-playbook/tiers/starter.just".source = ../justfiles/tiers/starter.just;
};
# System state version (do not change)
system.stateVersion = "24.11";
}

View File

@ -0,0 +1,26 @@
# 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.
{
lib,
modulesPath,
...
}: {
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = ["ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod"];
boot.initrd.kernelModules = [];
boot.kernelModules = [];
boot.extraModulePackages = [];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.ens18.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

37
modules/services.nix Normal file
View File

@ -0,0 +1,37 @@
# modules/services.nix
{
config,
lib,
tier ? "starter",
...
}:
with lib; let
tiers = {
starter = {
services = ["portainer" "caddy" "n8n"];
description = "Basic management tools";
};
premium = {
services = ["portainer" "caddy" "n8n" "baserow"];
description = "Automation and database tools";
};
};
in {
imports =
map
(serviceName: import ../services/${serviceName})
tiers.${tier}.services;
options.services.selfHostPlaybook = {
enable = mkEnableOption "self host playbook";
tier = mkOption {
type = types.enum ["starter" "premium"];
default = "starter";
description = "Service tier to enable";
};
};
config = mkIf config.services.selfHostPlaybook.enable {
# Add any additional configuration here if needed
};
}

View File

@ -0,0 +1,9 @@
{
virtualisation.oci-containers.containers.baserow = {
image = "docker.io/baserow/baserow:latest";
environmentFiles = ["/etc/environment-files/baserow.env"];
ports = ["127.0.0.1:3000:80"];
volumes = ["baserow_data:/baserow/data"];
extraOptions = ["--network=web"];
};
}

View File

@ -0,0 +1,3 @@
{
services.caddy.enable = true;
}

28
services/core/default.nix Normal file
View File

@ -0,0 +1,28 @@
{
imports = [
./baserow
./n8n
./portainer
];
virtualisation.oci-containers.backend = "docker";
systemd.services.docker-network-web = {
description = "Create Docker Network Web";
requires = ["docker.service"];
after = ["docker.service"];
wantedBy = ["multi-user.target"];
# Run on startup if network doesn't exist
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
if ! /run/current-system/sw/bin/docker network ls | grep -q 'web'; then
/run/current-system/sw/bin/docker network create web
fi
'';
};
}

9
services/n8n/default.nix Normal file
View File

@ -0,0 +1,9 @@
{
virtualisation.oci-containers.containers.n8n = {
image = "docker.io/n8nio/n8n:latest";
environmentFiles = ["/etc/environment-files/n8n.env"];
ports = ["127.0.0.1:5678:5678"];
volumes = ["n8n_data:/home/node/.n8n"];
extraOptions = ["--network=web"];
};
}

View File

@ -0,0 +1,11 @@
{
virtualisation.oci-containers.containers.portainer = {
image = "docker.io/portainer/portainer-ce:latest";
ports = ["127.0.0.1:9000:9000"];
volumes = [
"/etc/localtime:/etc/localtime:ro"
"/var/run/docker.sock:/var/run/docker.sock:ro"
"portainer_data:/data"
];
};
}