refactor: improve local development environment setup
This commit is contained in:
255
common.nix
255
common.nix
@@ -1,4 +1,4 @@
|
|||||||
{ pkgs, lib ? pkgs.lib, cloudServerNames, isLiveIso ? false, ... }:
|
{ pkgs, lib ? pkgs.lib, cloudServerNames, isLiveIso ? false, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
# Only include isoImage config when building ISO
|
# Only include isoImage config when building ISO
|
||||||
@@ -8,26 +8,62 @@ let
|
|||||||
makeUsbBootable = true;
|
makeUsbBootable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Complete Co-op Cloud recipe list (based on your ABRA_RECIPES.md and more)
|
# Complete Co-op Cloud recipe list (based on your ABRA_RECIPES.md and more)
|
||||||
allRecipes = [
|
allRecipes = [
|
||||||
# Tier 1 - Production Ready (Score 5)
|
# Tier 1 - Production Ready (Score 5)
|
||||||
"gitea" "mealie" "nextcloud"
|
"gitea"
|
||||||
|
"mealie"
|
||||||
|
"nextcloud"
|
||||||
|
|
||||||
# Tier 2 - Stable (Score 4)
|
# Tier 2 - Stable (Score 4)
|
||||||
"gotosocial" "wordpress"
|
"gotosocial"
|
||||||
|
"wordpress"
|
||||||
|
|
||||||
# Tier 3 - Community (Score 3)
|
# Tier 3 - Community (Score 3)
|
||||||
"collabora" "croc" "custom-php" "dokuwiki" "engelsystem" "fab-manager"
|
"collabora"
|
||||||
"ghost" "karrot" "lauti" "loomio" "mattermost" "mattermost-lts" "mrbs"
|
"croc"
|
||||||
"onlyoffice" "open-inventory" "outline" "owncast" "rallly"
|
"custom-php"
|
||||||
|
"dokuwiki"
|
||||||
|
"engelsystem"
|
||||||
|
"fab-manager"
|
||||||
|
"ghost"
|
||||||
|
"karrot"
|
||||||
|
"lauti"
|
||||||
|
"loomio"
|
||||||
|
"mattermost"
|
||||||
|
"mattermost-lts"
|
||||||
|
"mrbs"
|
||||||
|
"onlyoffice"
|
||||||
|
"open-inventory"
|
||||||
|
"outline"
|
||||||
|
"owncast"
|
||||||
|
"rallly"
|
||||||
|
|
||||||
# Additional recipes from Co-op Cloud catalog
|
# Additional recipes from Co-op Cloud catalog
|
||||||
"hedgedoc" "mediawiki" "seafile" "jitsi-meet" "matrix-synapse"
|
"hedgedoc"
|
||||||
"rocketchat" "prestashop" "invoiceninja" "kimai" "pretix"
|
"mediawiki"
|
||||||
"drone" "n8n" "gitlab" "jupyter-lab" "plausible" "matomo"
|
"seafile"
|
||||||
"uptime-kuma" "grafana" "peertube" "funkwhale" "mastodon"
|
"jitsi-meet"
|
||||||
"pixelfed" "jellyfin"
|
"matrix-synapse"
|
||||||
|
"rocketchat"
|
||||||
|
"prestashop"
|
||||||
|
"invoiceninja"
|
||||||
|
"kimai"
|
||||||
|
"pretix"
|
||||||
|
"drone"
|
||||||
|
"n8n"
|
||||||
|
"gitlab"
|
||||||
|
"jupyter-lab"
|
||||||
|
"plausible"
|
||||||
|
"matomo"
|
||||||
|
"uptime-kuma"
|
||||||
|
"grafana"
|
||||||
|
"peertube"
|
||||||
|
"funkwhale"
|
||||||
|
"mastodon"
|
||||||
|
"pixelfed"
|
||||||
|
"jellyfin"
|
||||||
];
|
];
|
||||||
in
|
in
|
||||||
|
|
||||||
@@ -35,10 +71,10 @@ isoConfig // {
|
|||||||
system.stateVersion = "25.05";
|
system.stateVersion = "25.05";
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
wireless.enable = false; # Disable to avoid conflicts
|
wireless.enable = false; # Disable to avoid conflicts
|
||||||
networkmanager = {
|
networkmanager = {
|
||||||
enable = true;
|
enable = true;
|
||||||
dns = "none"; # Critical: Don't let NetworkManager manage DNS
|
dns = "none"; # Critical: Don't let NetworkManager manage DNS
|
||||||
};
|
};
|
||||||
hostName = if isLiveIso then "workshop-live" else "workshop-vm";
|
hostName = if isLiveIso then "workshop-live" else "workshop-vm";
|
||||||
};
|
};
|
||||||
@@ -49,24 +85,24 @@ isoConfig // {
|
|||||||
settings = {
|
settings = {
|
||||||
# Wildcard: *.workshop.local -> 127.0.0.1
|
# Wildcard: *.workshop.local -> 127.0.0.1
|
||||||
address = "/.workshop.local/127.0.0.1";
|
address = "/.workshop.local/127.0.0.1";
|
||||||
|
|
||||||
# Use upstream DNS for everything else
|
# Use upstream DNS for everything else
|
||||||
server = [ "8.8.8.8" "1.1.1.1" ];
|
server = [ "8.8.8.8" "1.1.1.1" ];
|
||||||
|
|
||||||
# Listen on all interfaces (important for VM/container access)
|
# Listen on all interfaces (important for VM/container access)
|
||||||
listen-address = [ "127.0.0.1" ];
|
listen-address = [ "127.0.0.1" ];
|
||||||
|
|
||||||
# Bind to interfaces
|
# Bind to interfaces
|
||||||
bind-interfaces = true;
|
bind-interfaces = true;
|
||||||
|
|
||||||
# Don't read /etc/hosts for our custom domains
|
# Don't read /etc/hosts for our custom domains
|
||||||
no-hosts = false;
|
no-hosts = false;
|
||||||
|
|
||||||
# Cache settings
|
# Cache settings
|
||||||
cache-size = 1000;
|
cache-size = 1000;
|
||||||
log-queries = true;
|
log-queries = true;
|
||||||
log-dhcp = true;
|
log-dhcp = true;
|
||||||
|
|
||||||
# Local domain handling
|
# Local domain handling
|
||||||
local = "/workshop.local/";
|
local = "/workshop.local/";
|
||||||
domain-needed = true;
|
domain-needed = true;
|
||||||
@@ -108,7 +144,7 @@ isoConfig // {
|
|||||||
tree
|
tree
|
||||||
nano
|
nano
|
||||||
dnsutils
|
dnsutils
|
||||||
dig # For DNS debugging
|
dig # For DNS debugging
|
||||||
];
|
];
|
||||||
|
|
||||||
# Auto-install abra and setup Docker Swarm
|
# Auto-install abra and setup Docker Swarm
|
||||||
@@ -118,7 +154,7 @@ isoConfig // {
|
|||||||
wants = [ "network-online.target" ];
|
wants = [ "network-online.target" ];
|
||||||
script = ''
|
script = ''
|
||||||
export HOME=/home/workshop
|
export HOME=/home/workshop
|
||||||
|
|
||||||
# Wait for network and services with better testing
|
# Wait for network and services with better testing
|
||||||
echo "Waiting for services to start..."
|
echo "Waiting for services to start..."
|
||||||
for i in {1..30}; do
|
for i in {1..30}; do
|
||||||
@@ -129,7 +165,7 @@ isoConfig // {
|
|||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
# Test DNS resolution specifically
|
# Test DNS resolution specifically
|
||||||
for i in {1..20}; do
|
for i in {1..20}; do
|
||||||
if ${pkgs.dnsutils}/bin/nslookup test.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
if ${pkgs.dnsutils}/bin/nslookup test.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
||||||
@@ -139,7 +175,7 @@ isoConfig // {
|
|||||||
echo "🔄 Waiting for DNS... (attempt $i)"
|
echo "🔄 Waiting for DNS... (attempt $i)"
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
# Test Docker
|
# Test Docker
|
||||||
for i in {1..10}; do
|
for i in {1..10}; do
|
||||||
if ${pkgs.docker}/bin/docker info >/dev/null 2>&1; then
|
if ${pkgs.docker}/bin/docker info >/dev/null 2>&1; then
|
||||||
@@ -148,22 +184,22 @@ isoConfig // {
|
|||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
# Install abra for workshop user
|
# Install abra for workshop user
|
||||||
if [ ! -f /home/workshop/.local/bin/abra ]; then
|
if [ ! -f /home/workshop/.local/bin/abra ]; then
|
||||||
sudo -u workshop mkdir -p /home/workshop/.local/bin
|
sudo -u workshop mkdir -p /home/workshop/.local/bin
|
||||||
cd /home/workshop
|
cd /home/workshop
|
||||||
sudo -u workshop ${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | sudo -u workshop ${pkgs.bash}/bin/bash
|
sudo -u workshop ${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | sudo -u workshop ${pkgs.bash}/bin/bash
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Initialize Docker Swarm
|
# Initialize Docker Swarm
|
||||||
if ! ${pkgs.docker}/bin/docker info | grep -q "Swarm: active"; then
|
if ! ${pkgs.docker}/bin/docker info | grep -q "Swarm: active"; then
|
||||||
${pkgs.docker}/bin/docker swarm init --advertise-addr 127.0.0.1 2>/dev/null || true
|
${pkgs.docker}/bin/docker swarm init --advertise-addr 127.0.0.1 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure workshop user is in docker group
|
# Ensure workshop user is in docker group
|
||||||
usermod -aG docker workshop
|
usermod -aG docker workshop
|
||||||
|
|
||||||
# Test final DNS resolution
|
# Test final DNS resolution
|
||||||
if ${pkgs.dnsutils}/bin/nslookup test.workshop.local 127.0.0.1; then
|
if ${pkgs.dnsutils}/bin/nslookup test.workshop.local 127.0.0.1; then
|
||||||
echo "🎉 All services ready!"
|
echo "🎉 All services ready!"
|
||||||
@@ -185,7 +221,7 @@ isoConfig // {
|
|||||||
echo "🚀 CODE CRISPIES Workshop Environment"
|
echo "🚀 CODE CRISPIES Workshop Environment"
|
||||||
echo "Mode: Local Development + Cloud Access"
|
echo "Mode: Local Development + Cloud Access"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Test DNS immediately on login
|
# Test DNS immediately on login
|
||||||
if command -v nslookup &> /dev/null; then
|
if command -v nslookup &> /dev/null; then
|
||||||
if nslookup test.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
if nslookup test.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
||||||
@@ -208,7 +244,7 @@ isoConfig // {
|
|||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
cur="''${COMP_WORDS[COMP_CWORD]}"
|
cur="''${COMP_WORDS[COMP_CWORD]}"
|
||||||
prev="''${COMP_WORDS[COMP_CWORD-1]}"
|
prev="''${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
|
||||||
case "''${prev}" in
|
case "''${prev}" in
|
||||||
deploy|browser)
|
deploy|browser)
|
||||||
opts="$ALL_RECIPES"
|
opts="$ALL_RECIPES"
|
||||||
@@ -226,107 +262,144 @@ isoConfig // {
|
|||||||
|
|
||||||
setup-traefik() {
|
setup-traefik() {
|
||||||
echo "🔧 Setting up local Traefik proxy..."
|
echo "🔧 Setting up local Traefik proxy..."
|
||||||
|
|
||||||
# Test DNS first
|
# Test DNS first
|
||||||
if ! nslookup traefik.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
if ! nslookup traefik.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
||||||
echo "❌ DNS not resolving *.workshop.local"
|
echo "❌ DNS not resolving *.workshop.local"
|
||||||
echo "🔄 Restarting dnsmasq..."
|
echo "🔄 Restarting dnsmasq..."
|
||||||
sudo systemctl restart dnsmasq
|
sudo systemctl restart dnsmasq
|
||||||
sleep 3
|
sleep 3
|
||||||
|
|
||||||
if ! nslookup traefik.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
if ! nslookup traefik.workshop.local 127.0.0.1 >/dev/null 2>&1; then
|
||||||
echo "❌ DNS still not working!"
|
echo "❌ DNS still not working!"
|
||||||
echo "🔍 Debug info:"
|
|
||||||
echo " systemctl status dnsmasq"
|
|
||||||
echo " nslookup traefik.workshop.local 127.0.0.1"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "✅ DNS resolution working"
|
echo "✅ DNS resolution working"
|
||||||
|
|
||||||
# Rest of your existing setup-traefik function...
|
# Ensure Docker Swarm is initialized
|
||||||
|
if ! docker info 2>/dev/null | grep -q "Swarm: active"; then
|
||||||
|
echo "🔥 Initializing Docker Swarm..."
|
||||||
|
docker swarm init --advertise-addr 127.0.0.1 || true
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create proxy network (CRITICAL for Traefik)
|
||||||
|
if ! docker network ls | grep -q "proxy"; then
|
||||||
|
echo "📡 Creating proxy overlay network..."
|
||||||
|
docker network create -d overlay proxy
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure abra is available
|
||||||
if ! command -v abra &> /dev/null; then
|
if ! command -v abra &> /dev/null; then
|
||||||
echo "❌ Abra not found. Installing..."
|
echo "❌ Abra not found. Installing..."
|
||||||
sudo systemctl restart workshop-abra-setup
|
sudo systemctl restart workshop-abra-setup
|
||||||
sleep 5
|
sleep 5
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
fi
|
fi
|
||||||
# Ensure Docker Swarm is ready
|
|
||||||
if ! docker info 2>/dev/null | grep -q "Swarm: active"; then
|
# Check current server setup
|
||||||
echo "🔥 Initializing Docker Swarm..."
|
echo "📋 Current servers:"
|
||||||
docker swarm init --advertise-addr 127.0.0.1 || true
|
abra server ls || echo "No servers configured"
|
||||||
fi
|
|
||||||
# Create abra context if not exists
|
# Add local server if not exists (default name is "default")
|
||||||
if ! abra server ls 2>/dev/null | grep -q "workshop-local"; then
|
if ! abra server ls 2>/dev/null | grep -q "default"; then
|
||||||
echo "🏗 Creating local abra context..."
|
echo "🏗 Adding local server context..."
|
||||||
abra server add --local
|
abra server add --local
|
||||||
|
sleep 2
|
||||||
fi
|
fi
|
||||||
#echo "🚀 Deploying Traefik..."
|
|
||||||
#abra app new traefik -S --domain=traefik.workshop.local --server=workshop-local
|
# Verify server is accessible
|
||||||
#abra app deploy traefik.workshop.local
|
echo "📋 Servers after setup:"
|
||||||
|
abra server ls
|
||||||
# Wait for Traefik to be ready
|
|
||||||
echo "⏳ Waiting for Traefik to start..."
|
# Check if Traefik app already exists
|
||||||
for i in {1..30}; do
|
if abra app ls 2>/dev/null | grep -q "traefik"; then
|
||||||
if curl -s http://traefik.workshop.local >/dev/null 2>&1; then
|
echo "ℹ️ Traefik already configured"
|
||||||
echo "✅ Traefik deployed! Dashboard: http://traefik.workshop.local"
|
traefik_domain=$(abra app ls | grep traefik | awk \'{print $1}\' | head -1)
|
||||||
echo "🚀 Now you can deploy apps with 'deploy <recipe>'"
|
echo "📍 Existing Traefik: $traefik_domain"
|
||||||
|
else
|
||||||
|
echo "🚀 Creating new Traefik app..."
|
||||||
|
|
||||||
|
# Use proper server context (default, not workshop-local)
|
||||||
|
abra app new traefik --domain=traefik.workshop.local --server=default
|
||||||
|
|
||||||
|
# Configure Traefik environment
|
||||||
|
echo "⚙️ Configuring Traefik..."
|
||||||
|
traefik_env_file="$HOME/.abra/servers/default/traefik.workshop.local.env"
|
||||||
|
|
||||||
|
if [ -f "$traefik_env_file" ]; then
|
||||||
|
# Set required environment variables
|
||||||
|
if ! grep -q "LETS_ENCRYPT_EMAIL" "$traefik_env_file"; then
|
||||||
|
echo "LETS_ENCRYPT_EMAIL=workshop@local.dev" >> "$traefik_env_file"
|
||||||
|
fi
|
||||||
|
if ! grep -q "DASHBOARD_ENABLED" "$traefik_env_file"; then
|
||||||
|
echo "DASHBOARD_ENABLED=true" >> "$traefik_env_file"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "⚠️ Traefik env file not found at: $traefik_env_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "📦 Deploying Traefik..."
|
||||||
|
abra app deploy traefik.workshop.local
|
||||||
|
|
||||||
|
traefik_domain="traefik.workshop.local"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for Traefik to be ready
|
||||||
|
echo "⏳ Waiting for Traefik to be ready..."
|
||||||
|
for i in {1..60}; do
|
||||||
|
if curl -s --connect-timeout 3 --max-time 5 http://traefik.workshop.local/ping >/dev/null 2>&1; then
|
||||||
|
echo "✅ Traefik is ready! Dashboard: http://traefik.workshop.local"
|
||||||
|
echo "🚀 You can now deploy apps with: deploy <recipe>"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "⚠️ Traefik deployed but may still be starting..."
|
echo "⚠️ Traefik deployment timed out but may still be starting..."
|
||||||
echo "🔍 Debug: docker service ls | curl -I http://traefik.workshop.local"
|
echo ""
|
||||||
|
echo "🔍 Debug commands:"
|
||||||
|
echo " abra app ps traefik.workshop.local"
|
||||||
|
echo " abra app logs traefik.workshop.local"
|
||||||
|
echo " docker service ls"
|
||||||
|
echo " docker service logs \$(docker service ls --filter name=traefik -q)"
|
||||||
}
|
}
|
||||||
|
|
||||||
deploy() {
|
deploy() {
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo "Usage: deploy <recipe>"
|
echo "Usage: deploy <recipe>"
|
||||||
echo "Example: deploy wordpress"
|
|
||||||
echo "Available recipes: $ALL_RECIPES"
|
echo "Available recipes: $ALL_RECIPES"
|
||||||
echo ""
|
|
||||||
echo "🔍 Use tab completion or run 'recipes' for categorized list"
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local recipe="$1"
|
local recipe="$1"
|
||||||
local domain="$recipe.workshop.local"
|
local domain="$recipe.workshop.local"
|
||||||
|
|
||||||
echo "🚀 Deploying $recipe locally..."
|
echo "🚀 Deploying $recipe locally..."
|
||||||
echo "Domain: $domain"
|
echo "Domain: $domain"
|
||||||
|
# Ensure Traefik is running first
|
||||||
if ! command -v abra &> /dev/null; then
|
if ! curl -s --max-time 3 http://traefik.workshop.local/ping >/dev/null 2>&1; then
|
||||||
echo "❌ Abra not found. Run 'sudo systemctl restart workshop-abra-setup'"
|
echo "⚠️ Traefik not responding. Setting up..."
|
||||||
return 1
|
setup-traefik || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if Traefik is running
|
|
||||||
if ! curl -s http://traefik.workshop.local >/dev/null 2>&1; then
|
|
||||||
echo "⚠️ Traefik not detected. Running setup first..."
|
|
||||||
setup-traefik
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "📦 Creating app: $recipe"
|
echo "📦 Creating app: $recipe"
|
||||||
abra app new "$recipe" -S --domain="$domain" --server=workshop-local
|
# Use correct server name
|
||||||
|
abra app new "$recipe" --domain="$domain" --server=default -S 2>/dev/null || \
|
||||||
|
abra app new "$recipe" --domain="$domain" --server=default
|
||||||
echo "🚀 Deploying app: $domain"
|
echo "🚀 Deploying app: $domain"
|
||||||
abra app deploy "$domain"
|
abra app deploy "$domain"
|
||||||
|
|
||||||
echo "⏳ Waiting for deployment..."
|
echo "⏳ Waiting for deployment..."
|
||||||
for i in {1..60}; do
|
for i in {1..60}; do
|
||||||
if curl -s http://$domain >/dev/null 2>&1; then
|
if curl -s --max-time 3 http://$domain >/dev/null 2>&1; then
|
||||||
echo "✅ Deployed! Access at: http://$domain"
|
echo "✅ Deployed! Access at: http://$domain"
|
||||||
echo "🌐 Quick launch: browser $recipe"
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
sleep 3
|
sleep 3
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "⚠️ Deployment completed but app may still be starting..."
|
echo "⚠️ Deployment may still be starting..."
|
||||||
echo "🔍 Debug: docker service ls | dig @127.0.0.1 $domain +short"
|
echo "🔍 Debug: abra app ps $domain"
|
||||||
echo "🌐 Try: browser $recipe (in a few moments)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
@@ -337,7 +410,7 @@ isoConfig // {
|
|||||||
|
|
||||||
browser() {
|
browser() {
|
||||||
local target_url="about:blank"
|
local target_url="about:blank"
|
||||||
|
|
||||||
if [ -n "$1" ]; then
|
if [ -n "$1" ]; then
|
||||||
# Specific app requested
|
# Specific app requested
|
||||||
target_url="http://$1.workshop.local"
|
target_url="http://$1.workshop.local"
|
||||||
@@ -345,7 +418,7 @@ isoConfig // {
|
|||||||
else
|
else
|
||||||
echo "🌐 Opening Firefox browser"
|
echo "🌐 Opening Firefox browser"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$DISPLAY" ]; then
|
if [ -n "$DISPLAY" ]; then
|
||||||
firefox "$target_url" &
|
firefox "$target_url" &
|
||||||
else
|
else
|
||||||
@@ -360,7 +433,7 @@ isoConfig // {
|
|||||||
echo "⭐ Tier 1 - Production Ready (Score 5):"
|
echo "⭐ Tier 1 - Production Ready (Score 5):"
|
||||||
echo " gitea mealie nextcloud"
|
echo " gitea mealie nextcloud"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🔧 Tier 2 - Stable (Score 4):"
|
echo "🔧 Tier 2 - Stable (Score 4):"
|
||||||
echo " gotosocial wordpress"
|
echo " gotosocial wordpress"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🧪 Tier 3 - Community (Score 3):"
|
echo "🧪 Tier 3 - Community (Score 3):"
|
||||||
|
|||||||
62
flake.nix
62
flake.nix
@@ -17,7 +17,7 @@
|
|||||||
# Server names for cloud connections
|
# Server names for cloud connections
|
||||||
cloudServerNames = [
|
cloudServerNames = [
|
||||||
"hopper"
|
"hopper"
|
||||||
"curie"
|
"curie"
|
||||||
"lovelace"
|
"lovelace"
|
||||||
"noether"
|
"noether"
|
||||||
"hamilton"
|
"hamilton"
|
||||||
@@ -34,8 +34,8 @@
|
|||||||
];
|
];
|
||||||
|
|
||||||
# Common configuration
|
# Common configuration
|
||||||
commonConfig = { isLiveIso ? false }:
|
commonConfig = { isLiveIso ? false }:
|
||||||
import ./common.nix {
|
import ./common.nix {
|
||||||
inherit pkgs cloudServerNames isLiveIso;
|
inherit pkgs cloudServerNames isLiveIso;
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
@@ -64,39 +64,41 @@
|
|||||||
inherit system;
|
inherit system;
|
||||||
modules = [
|
modules = [
|
||||||
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
|
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
|
||||||
|
|
||||||
(commonConfig { isLiveIso = false; })
|
(commonConfig { isLiveIso = false; })
|
||||||
|
|
||||||
({ config, pkgs, lib, ... }: {
|
({ config, pkgs, lib, ... }: {
|
||||||
boot.loader.grub.enable = false;
|
boot.loader.grub.enable = false;
|
||||||
boot.loader.generic-extlinux-compatible.enable = true;
|
boot.loader.generic-extlinux-compatible.enable = true;
|
||||||
|
|
||||||
# Enable networking for VM
|
# Enable networking for VM
|
||||||
networking.hostName = "workshop-vm";
|
networking.hostName = "workshop-vm";
|
||||||
networking.networkmanager.enable = true;
|
networking.networkmanager.enable = true;
|
||||||
networking.firewall.enable = false;
|
networking.firewall.enable = false;
|
||||||
|
|
||||||
# Hybrid console configuration - serial primary, GUI available
|
# Hybrid console configuration - serial primary, GUI available
|
||||||
boot.kernelParams = [ "console=ttyS0,115200" "console=tty1" ];
|
boot.kernelParams = [ "console=ttyS0,115200" "console=tty1" ];
|
||||||
|
|
||||||
# VM specific settings
|
# VM specific settings
|
||||||
virtualisation.memorySize = 4096;
|
virtualisation.memorySize = 4096;
|
||||||
virtualisation.diskSize = 40000;
|
virtualisation.diskSize = 40000;
|
||||||
|
|
||||||
# Hybrid mode: GUI available but serial console primary
|
# Hybrid mode: GUI available but serial console primary
|
||||||
virtualisation.qemu.options = [
|
virtualisation.qemu.options = [
|
||||||
"-display" "gtk"
|
"-display"
|
||||||
"-monitor" "stdio"
|
"gtk"
|
||||||
];
|
"-monitor"
|
||||||
# Fix the auto-login conflict with mkForce
|
"stdio"
|
||||||
services.displayManager.autoLogin = lib.mkForce {
|
];
|
||||||
enable = true;
|
# Fix the auto-login conflict with mkForce
|
||||||
user = "workshop";
|
services.displayManager.autoLogin = lib.mkForce {
|
||||||
};
|
enable = true;
|
||||||
# Keep GUI session commands for when GUI is used
|
user = "workshop";
|
||||||
services.xserver.displayManager.sessionCommands = ''
|
};
|
||||||
${pkgs.xfce.xfce4-terminal}/bin/xfce4-terminal --fullscreen --title="Workshop Terminal" &
|
# Keep GUI session commands for when GUI is used
|
||||||
'';
|
services.xserver.displayManager.sessionCommands = ''
|
||||||
|
${pkgs.xfce.xfce4-terminal}/bin/xfce4-terminal --fullscreen --title="Workshop Terminal" &
|
||||||
|
'';
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user