fix: simplify systemd service script for workshop setup
This commit is contained in:
285
common.nix
285
common.nix
@@ -9,7 +9,7 @@ let
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Complete Co-op Cloud recipe list (based on your ABRA_RECIPES.md and more)
|
# Complete Co-op Cloud recipe list
|
||||||
allRecipes = [
|
allRecipes = [
|
||||||
# Tier 1 - Production Ready (Score 5)
|
# Tier 1 - Production Ready (Score 5)
|
||||||
"gitea"
|
"gitea"
|
||||||
@@ -40,7 +40,7 @@ let
|
|||||||
"owncast"
|
"owncast"
|
||||||
"rallly"
|
"rallly"
|
||||||
|
|
||||||
# Additional recipes from Co-op Cloud catalog
|
# Extended catalog
|
||||||
"hedgedoc"
|
"hedgedoc"
|
||||||
"mediawiki"
|
"mediawiki"
|
||||||
"seafile"
|
"seafile"
|
||||||
@@ -65,11 +65,12 @@ let
|
|||||||
"pixelfed"
|
"pixelfed"
|
||||||
"jellyfin"
|
"jellyfin"
|
||||||
];
|
];
|
||||||
in
|
|
||||||
|
|
||||||
|
in
|
||||||
isoConfig // {
|
isoConfig // {
|
||||||
system.stateVersion = "25.05";
|
system.stateVersion = "25.05";
|
||||||
|
|
||||||
|
# SSH Configuration
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
@@ -80,69 +81,55 @@ isoConfig // {
|
|||||||
ports = [ 22 ];
|
ports = [ 22 ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Network Configuration
|
||||||
networking = {
|
networking = {
|
||||||
wireless.enable = false;
|
wireless.enable = false;
|
||||||
networkmanager = {
|
networkmanager = {
|
||||||
enable = true;
|
enable = true;
|
||||||
dns = "none";
|
dns = "none"; # We use dnsmasq
|
||||||
};
|
};
|
||||||
hostName = if isLiveIso then "workshop-live" else "workshop-vm";
|
hostName = if isLiveIso then "workshop-live" else "workshop-vm";
|
||||||
hosts = {
|
hosts."127.0.0.1" = [ "workshop.local" "localhost" ];
|
||||||
"127.0.0.1" = [ "workshop.local" "localhost" ];
|
nameservers = lib.mkForce [ "127.0.0.1" ];
|
||||||
};
|
firewall.enable = false; # Workshop environment
|
||||||
};
|
};
|
||||||
|
|
||||||
# Configure dnsmasq properly for wildcard DNS
|
# DNS Configuration - Wildcard *.workshop.local -> 127.0.0.1
|
||||||
services.dnsmasq = {
|
services.dnsmasq = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
# 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
|
|
||||||
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-address = [ "127.0.0.1" ];
|
listen-address = [ "127.0.0.1" ];
|
||||||
|
|
||||||
# Bind to interfaces
|
|
||||||
bind-interfaces = true;
|
bind-interfaces = true;
|
||||||
|
|
||||||
# Don't read /etc/hosts for our custom domains
|
|
||||||
no-hosts = false;
|
|
||||||
|
|
||||||
# Cache settings
|
|
||||||
cache-size = 1000;
|
cache-size = 1000;
|
||||||
log-queries = true;
|
|
||||||
log-dhcp = true;
|
|
||||||
|
|
||||||
# Local domain handling
|
|
||||||
local = "/workshop.local/";
|
local = "/workshop.local/";
|
||||||
domain-needed = true;
|
domain-needed = true;
|
||||||
bogus-priv = true;
|
bogus-priv = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Force system to use our dnsmasq
|
# Disable systemd-resolved (conflicts with dnsmasq)
|
||||||
networking.nameservers = lib.mkForce [ "127.0.0.1" ];
|
|
||||||
|
|
||||||
# Disable systemd-resolved to avoid conflicts
|
|
||||||
services.resolved.enable = false;
|
services.resolved.enable = false;
|
||||||
|
|
||||||
# Enable Docker for local development
|
# Container Runtime
|
||||||
virtualisation.docker.enable = true;
|
virtualisation.docker.enable = true;
|
||||||
|
|
||||||
services.getty.autologinUser = "workshop";
|
# User Configuration
|
||||||
users.users.root.password = "root";
|
users = {
|
||||||
users.users.workshop = {
|
users.root.password = "root";
|
||||||
|
users.workshop = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
shell = pkgs.bash;
|
shell = pkgs.bash;
|
||||||
extraGroups = [ "networkmanager" "wheel" "docker" ];
|
extraGroups = [ "networkmanager" "wheel" "docker" ];
|
||||||
password = "workshop";
|
password = "workshop";
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.getty.autologinUser = "workshop";
|
||||||
security.sudo.wheelNeedsPassword = false;
|
security.sudo.wheelNeedsPassword = false;
|
||||||
|
|
||||||
|
# System Packages
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
openssh
|
openssh
|
||||||
curl
|
curl
|
||||||
@@ -157,30 +144,27 @@ isoConfig // {
|
|||||||
tree
|
tree
|
||||||
nano
|
nano
|
||||||
dnsutils
|
dnsutils
|
||||||
dig # For DNS debugging
|
dig
|
||||||
];
|
];
|
||||||
|
|
||||||
# Auto-install abra and setup Docker Swarm
|
# Workshop Setup Service - REFACTORED
|
||||||
systemd.services.workshop-abra-setup = {
|
systemd.services.workshop-abra-setup = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network-online.target" "docker.service" "dnsmasq.service" ];
|
after = [ "network-online.target" "docker.service" "dnsmasq.service" ];
|
||||||
wants = [ "network-online.target" ];
|
wants = [ "network-online.target" ];
|
||||||
script = ''
|
script = ''
|
||||||
export HOME=/home/workshop
|
# Wait for network and services
|
||||||
export PATH="/run/current-system/sw/bin:/usr/bin:/bin"
|
|
||||||
# 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
|
||||||
# Test external connectivity
|
if curl -s --max-time 3 google.com >/dev/null 2>&1; then
|
||||||
if /run/current-system/sw/bin/curl -s --max-time 3 google.com >/dev/null 2>&1; then
|
|
||||||
echo "✅ External network ready"
|
echo "✅ External network ready"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
# Test DNS resolution specifically
|
# Test DNS resolution
|
||||||
for i in {1..20}; do
|
for i in {1..20}; do
|
||||||
if /run/current-system/sw/bin/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
|
||||||
echo "✅ Wildcard DNS ready"
|
echo "✅ Wildcard DNS ready"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -189,7 +173,7 @@ isoConfig // {
|
|||||||
done
|
done
|
||||||
# Test Docker
|
# Test Docker
|
||||||
for i in {1..10}; do
|
for i in {1..10}; do
|
||||||
if /run/current-system/sw/bin/docker info >/dev/null 2>&1; then
|
if docker info >/dev/null 2>&1; then
|
||||||
echo "✅ Docker ready"
|
echo "✅ Docker ready"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
@@ -198,24 +182,22 @@ isoConfig // {
|
|||||||
# 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
|
||||||
echo "🚀 Installing abra for user workshop..."
|
echo "🚀 Installing abra for user workshop..."
|
||||||
/usr/bin/su - workshop -c "mkdir -p /home/workshop/.local/bin"
|
sudo -u workshop bash -c "mkdir -p /home/workshop/.local/bin"
|
||||||
# Run installer and log output
|
sudo -u workshop bash -c "curl -fsSL https://install.abra.coopcloud.tech | bash"
|
||||||
install_log="/tmp/abra-install.log"
|
|
||||||
/usr/bin/su - workshop -c "bash -c \"cd /home/workshop && /run/current-system/sw/bin/curl -fsSL https://install.abra.coopcloud.tech | bash\"" &> "$install_log"
|
|
||||||
if [ -f /home/workshop/.local/bin/abra ]; then
|
if [ -f /home/workshop/.local/bin/abra ]; then
|
||||||
echo "✅ abra installed successfully."
|
echo "✅ abra installed successfully."
|
||||||
else
|
else
|
||||||
echo "❌ abra installation failed. See logs: cat $install_log"
|
echo "❌ abra installation failed."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "✅ abra already installed."
|
echo "✅ abra already installed."
|
||||||
fi
|
fi
|
||||||
# Initialize Docker Swarm
|
# Initialize Docker Swarm
|
||||||
echo "🔄 Checking Docker Swarm status..."
|
echo "🔄 Checking Docker Swarm status..."
|
||||||
if ! /run/current-system/sw/bin/docker info | grep -q "Swarm: active"; then
|
if ! docker info | grep -q "Swarm: active"; then
|
||||||
echo "🔥 Initializing Docker Swarm..."
|
echo "🔥 Initializing Docker Swarm..."
|
||||||
/run/current-system/sw/bin/docker swarm init --advertise-addr 127.0.0.1 2>/dev/null || true
|
docker swarm init --advertise-addr 127.0.0.1 2>/dev/null || true
|
||||||
if /run/current-system/sw/bin/docker info | grep -q "Swarm: active"; then
|
if docker info | grep -q "Swarm: active"; then
|
||||||
echo "✅ Docker Swarm initialized."
|
echo "✅ Docker Swarm initialized."
|
||||||
else
|
else
|
||||||
echo "❌ Docker Swarm initialization failed."
|
echo "❌ Docker Swarm initialization failed."
|
||||||
@@ -225,22 +207,18 @@ isoConfig // {
|
|||||||
fi
|
fi
|
||||||
# Ensure workshop user is in docker group
|
# Ensure workshop user is in docker group
|
||||||
echo "🔄 Ensuring workshop user is in docker group..."
|
echo "🔄 Ensuring workshop user is in docker group..."
|
||||||
/usr/bin/usermod -aG docker workshop
|
usermod -aG docker workshop
|
||||||
if id -nG workshop | grep -q "docker"; then
|
if id -nG workshop | grep -q "docker"; then
|
||||||
echo "✅ workshop user is in docker group."
|
echo "✅ workshop user is in docker group."
|
||||||
else
|
else
|
||||||
echo "❌ Failed to add workshop user to docker group."
|
echo "❌ Failed to add workshop user to docker group."
|
||||||
fi
|
fi
|
||||||
# Create proper abra server configuration
|
|
||||||
if [ ! -f /home/workshop/.abra/servers/workshop.local.env ]; then
|
|
||||||
/usr/bin/su - workshop -c "mkdir -p /home/workshop/.abra/servers/"
|
|
||||||
fi
|
|
||||||
# Set up autocomplete
|
# Set up autocomplete
|
||||||
if command -v abra &> /dev/null; then
|
if command -v abra &> /dev/null; then
|
||||||
/run/current-system/sw/bin/su - workshop -c "source <(/home/workshop/.local/bin/abra autocomplete bash)"
|
sudo -u workshop bash -c "source <(/home/workshop/.local/bin/abra autocomplete bash)"
|
||||||
fi
|
fi
|
||||||
# Test final DNS resolution
|
# Test final DNS resolution
|
||||||
if /run/current-system/sw/bin/nslookup test.workshop.local 127.0.0.1; then
|
if nslookup test.workshop.local 127.0.0.1; then
|
||||||
echo "🎉 All services ready!"
|
echo "🎉 All services ready!"
|
||||||
else
|
else
|
||||||
echo "⚠️ DNS may need manual restart: sudo systemctl restart dnsmasq"
|
echo "⚠️ DNS may need manual restart: sudo systemctl restart dnsmasq"
|
||||||
@@ -250,106 +228,97 @@ isoConfig // {
|
|||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
User = "root";
|
User = "root";
|
||||||
Environment = [
|
|
||||||
"PATH=/run/current-system/sw/bin:/usr/bin:/bin"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# Enhanced bash configuration with complete recipe support
|
# Enhanced Bash Configuration with All Features
|
||||||
programs.bash = {
|
programs.bash.interactiveShellInit =
|
||||||
interactiveShellInit = ''
|
let
|
||||||
# Workshop welcome and command definitions
|
recipeList = builtins.concatStringsSep " " allRecipes;
|
||||||
|
serverList = builtins.concatStringsSep " " cloudServerNames;
|
||||||
|
in
|
||||||
|
''
|
||||||
|
# Workshop Environment Welcome
|
||||||
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
|
# DNS Health Check
|
||||||
if command -v nslookup &> /dev/null; then
|
if command -v nslookup >/dev/null 2>&1; 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
|
||||||
echo "✅ DNS wildcard ready: *.workshop.local → 127.0.0.1"
|
echo "✅ DNS wildcard ready: *.workshop.local → 127.0.0.1"
|
||||||
else
|
else
|
||||||
echo "❌ DNS not working! Run: sudo systemctl restart dnsmasq"
|
echo "⚠️ DNS not working! Run: sudo systemctl restart dnsmasq"
|
||||||
echo "🔧 Debug: nslookup test.workshop.local 127.0.0.1"
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure abra is in PATH
|
# Ensure abra is in PATH
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
# Complete recipe list for bash completion
|
# Bash Completion Configuration
|
||||||
ALL_RECIPES="${builtins.concatStringsSep " " allRecipes}"
|
|
||||||
|
|
||||||
# Enable tab completion for deploy and browser commands
|
|
||||||
_workshop_completion() {
|
_workshop_completion() {
|
||||||
local cur prev opts
|
local cur prev
|
||||||
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"
|
COMPREPLY=($(compgen -W "${recipeList}" -- "$cur"))
|
||||||
COMPREPLY=( $(compgen -W "''${opts}" -- ''${cur}) )
|
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
connect)
|
connect)
|
||||||
opts="${builtins.concatStringsSep " " cloudServerNames}"
|
COMPREPLY=($(compgen -W "${serverList}" -- "$cur"))
|
||||||
COMPREPLY=( $(compgen -W "''${opts}" -- ''${cur}) )
|
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
complete -F _workshop_completion deploy browser connect
|
complete -F _workshop_completion deploy browser connect
|
||||||
|
|
||||||
|
# Core Workshop Functions
|
||||||
setup-traefik() {
|
setup-traefik() {
|
||||||
echo "🔧 Setting up local Traefik proxy..."
|
echo "🔧 Setting up local Traefik proxy..."
|
||||||
|
|
||||||
# Ensure we can SSH to workshop.local first (tutorial requirement)
|
# Test SSH capability (tutorial requirement)
|
||||||
if ! ssh -o ConnectTimeout=3 -o BatchMode=yes workshop@workshop.local echo "SSH OK" 2>/dev/null; then
|
if ! timeout 3 ssh -o BatchMode=yes workshop@workshop.local echo "SSH OK" 2>/dev/null; then
|
||||||
echo "⚠️ SSH to workshop.local not working, but continuing with local setup..."
|
echo "⚠️ SSH to workshop.local not working, continuing with local setup..."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# DNS check
|
# Verify DNS
|
||||||
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 "🔄 Restarting DNS..."
|
||||||
sudo systemctl restart dnsmasq
|
sudo systemctl restart dnsmasq
|
||||||
sleep 3
|
sleep 3
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Docker Swarm + proxy network
|
# Ensure Docker Swarm + proxy network
|
||||||
if ! docker info 2>/dev/null | grep -q "Swarm: active"; then
|
if ! docker info 2>/dev/null | grep -q "Swarm: active"; then
|
||||||
echo "🔥 Initializing Docker Swarm..."
|
echo "🔥 Initializing Docker Swarm..."
|
||||||
docker swarm init --advertise-addr 127.0.0.1
|
docker swarm init --advertise-addr 127.0.0.1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! docker network ls | grep -q "proxy"; then
|
if ! docker network ls | grep -q "proxy"; then
|
||||||
echo "📡 Creating proxy overlay network..."
|
echo "🌐 Creating proxy network..."
|
||||||
docker network create -d overlay proxy
|
docker network create -d overlay proxy
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Add server (tutorial step)
|
# Add server
|
||||||
if ! abra server ls 2>/dev/null | grep -q "workshop.local"; then
|
if ! abra server ls 2>/dev/null | grep -q "workshop.local"; then
|
||||||
echo "🏗 Adding workshop.local server..."
|
echo "🏗️ Adding workshop.local server..."
|
||||||
# Try to add as proper domain first, fallback to --local
|
|
||||||
abra server add workshop.local 2>/dev/null || abra server add --local
|
abra server add workshop.local 2>/dev/null || abra server add --local
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create Traefik app (tutorial step 1)
|
# Create, configure, and deploy Traefik
|
||||||
if ! abra app ls 2>/dev/null | grep -q "traefik"; then
|
if ! abra app ls 2>/dev/null | grep -q "traefik"; then
|
||||||
echo "🚀 Creating Traefik app..."
|
echo "🚀 Creating Traefik app..."
|
||||||
abra app new traefik --domain=traefik.workshop.local
|
abra app new traefik --domain=traefik.workshop.local
|
||||||
fi
|
|
||||||
|
|
||||||
# Configure Traefik (tutorial step 2)
|
|
||||||
echo "⚙️ Configuring Traefik..."
|
echo "⚙️ Configuring Traefik..."
|
||||||
abra app config traefik.workshop.local
|
abra app config traefik.workshop.local
|
||||||
|
|
||||||
# Deploy Traefik (tutorial step 3)
|
|
||||||
echo "📦 Deploying Traefik..."
|
echo "📦 Deploying Traefik..."
|
||||||
abra app deploy traefik.workshop.local
|
abra app deploy traefik.workshop.local
|
||||||
|
|
||||||
# Wait and verify
|
|
||||||
echo "⏳ Waiting for Traefik..."
|
echo "⏳ Waiting for Traefik..."
|
||||||
for i in {1..30}; do
|
for i in {1..30}; do
|
||||||
if curl -s http://traefik.workshop.local >/dev/null 2>&1; then
|
if curl -s http://traefik.workshop.local >/dev/null 2>&1; then
|
||||||
@@ -360,29 +329,38 @@ isoConfig // {
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "⚠️ Traefik may still be starting. Check: abra app logs traefik.workshop.local"
|
echo "⚠️ Traefik may still be starting. Check: abra app logs traefik.workshop.local"
|
||||||
|
else
|
||||||
|
echo "✅ Traefik already exists"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
deploy() {
|
deploy() {
|
||||||
if [ -z "$1" ]; then
|
if [[ -z "$1" ]]; then
|
||||||
echo "Usage: deploy <recipe>"
|
echo "Usage: deploy <recipe>"
|
||||||
echo "Available recipes: $ALL_RECIPES"
|
echo "Available: ${recipeList}"
|
||||||
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
|
|
||||||
|
# Ensure Traefik is running
|
||||||
if ! curl -s --max-time 3 http://traefik.workshop.local/ping >/dev/null 2>&1; then
|
if ! curl -s --max-time 3 http://traefik.workshop.local/ping >/dev/null 2>&1; then
|
||||||
echo "⚠️ Traefik not responding. Setting up..."
|
echo "⚠️ Traefik not responding. Setting up..."
|
||||||
setup-traefik || return 1
|
setup-traefik || return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Create and deploy app
|
||||||
echo "📦 Creating app: $recipe"
|
echo "📦 Creating app: $recipe"
|
||||||
# Use correct server name
|
abra app new "$recipe" --domain="$domain" --server=default 2>/dev/null || \
|
||||||
abra app new "$recipe" --domain="$domain" --server=default -S 2>/dev/null || \
|
abra app new "$recipe" --domain="$domain"
|
||||||
abra app new "$recipe" --domain="$domain" --server=default
|
|
||||||
echo "🚀 Deploying app: $domain"
|
echo "🚀 Deploying: $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 --max-time 3 http://$domain >/dev/null 2>&1; then
|
if curl -s --max-time 3 http://$domain >/dev/null 2>&1; then
|
||||||
@@ -397,7 +375,11 @@ isoConfig // {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
[ -z "$1" ] && { echo "Usage: connect <name>"; echo "Available: ${builtins.concatStringsSep " " cloudServerNames}"; return 1; }
|
if [[ -z "$1" ]]; then
|
||||||
|
echo "Usage: connect <name>"
|
||||||
|
echo "Available: ${serverList}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
echo "🔌 Connecting to $1.codecrispi.es..."
|
echo "🔌 Connecting to $1.codecrispi.es..."
|
||||||
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
||||||
}
|
}
|
||||||
@@ -405,15 +387,14 @@ isoConfig // {
|
|||||||
browser() {
|
browser() {
|
||||||
local target_url="about:blank"
|
local target_url="about:blank"
|
||||||
|
|
||||||
if [ -n "$1" ]; then
|
if [[ -n "$1" ]]; then
|
||||||
# Specific app requested
|
|
||||||
target_url="http://$1.workshop.local"
|
target_url="http://$1.workshop.local"
|
||||||
echo "🌐 Opening $1 at $target_url"
|
echo "🌐 Opening $1 at $target_url"
|
||||||
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
|
||||||
echo "❌ No GUI session. Run 'desktop' first"
|
echo "❌ No GUI session. Run 'desktop' first"
|
||||||
@@ -424,111 +405,73 @@ isoConfig // {
|
|||||||
recipes() {
|
recipes() {
|
||||||
echo "📚 Complete Co-op Cloud Recipe Catalog:"
|
echo "📚 Complete Co-op Cloud Recipe Catalog:"
|
||||||
echo ""
|
echo ""
|
||||||
echo "⭐ Tier 1 - Production Ready (Score 5):"
|
echo "⭐ Tier 1 - Production Ready: gitea mealie nextcloud"
|
||||||
echo " gitea mealie nextcloud"
|
echo "🔧 Tier 2 - Stable: gotosocial wordpress"
|
||||||
echo ""
|
echo "🧪 Tier 3 - Community: collabora croc dokuwiki ghost loomio..."
|
||||||
echo "🔧 Tier 2 - Stable (Score 4):"
|
echo "🌐 Extended: matrix-synapse rocketchat gitlab n8n mastodon..."
|
||||||
echo " gotosocial wordpress"
|
|
||||||
echo ""
|
|
||||||
echo "🧪 Tier 3 - Community (Score 3):"
|
|
||||||
echo " collabora croc custom-php dokuwiki engelsystem"
|
|
||||||
echo " fab-manager ghost karrot lauti loomio mattermost"
|
|
||||||
echo " mattermost-lts mrbs onlyoffice open-inventory outline"
|
|
||||||
echo " owncast rallly"
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Extended Catalog:"
|
|
||||||
echo " Content: hedgedoc mediawiki seafile"
|
|
||||||
echo " Chat: jitsi-meet matrix-synapse rocketchat"
|
|
||||||
echo " Business: prestashop invoiceninja kimai pretix"
|
|
||||||
echo " Dev Tools: drone n8n gitlab jupyter-lab"
|
|
||||||
echo " Analytics: plausible matomo uptime-kuma grafana"
|
|
||||||
echo " Media: peertube funkwhale mastodon pixelfed jellyfin"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "🚀 Usage:"
|
echo "🚀 Usage:"
|
||||||
echo " deploy <recipe> - Deploy locally"
|
echo " deploy <recipe> - Deploy locally"
|
||||||
echo " browser <recipe> - Open app in browser"
|
echo " browser <recipe> - Open in browser"
|
||||||
echo " 📖 Full catalog: https://recipes.coopcloud.tech"
|
echo " 📖 Full catalog: https://recipes.coopcloud.tech"
|
||||||
echo ""
|
echo ""
|
||||||
echo "💡 Use tab completion: type 'deploy <TAB>' or 'browser <TAB>'"
|
echo "💡 Tab completion: deploy <TAB> or browser <TAB>"
|
||||||
}
|
}
|
||||||
|
|
||||||
desktop() {
|
desktop() {
|
||||||
echo "🖥️ Starting GUI session..."
|
echo "🖥️ Starting GUI session..."
|
||||||
if command -v startx &> /dev/null; then
|
if command -v startx >/dev/null 2>&1; then
|
||||||
if [ -z "$DISPLAY" ]; then
|
if [[ -z "$DISPLAY" ]]; then
|
||||||
startx &
|
startx &
|
||||||
export DISPLAY=:0
|
export DISPLAY=:0
|
||||||
sleep 3
|
sleep 3
|
||||||
echo "✅ GUI started. Check QEMU window or run 'browser'"
|
echo "✅ GUI started"
|
||||||
else
|
else
|
||||||
echo "ℹ️ GUI already running"
|
echo "ℹ️ GUI already running"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "💡 GUI available in QEMU window (Alt+Tab to switch)"
|
echo "💡 GUI available in QEMU window"
|
||||||
echo "🖱️ Click on QEMU graphics window to use desktop"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
abra-status() {
|
abra-status() {
|
||||||
echo "🔍 Checking workshop-abra-setup service status..."
|
echo "🔍 Workshop setup service status:"
|
||||||
systemctl status workshop-abra-setup
|
systemctl status workshop-abra-setup --no-pager
|
||||||
echo ""
|
echo ""
|
||||||
if [ -f /tmp/abra-install.log ]; then
|
echo "💡 Commands: which abra | abra --version"
|
||||||
echo "📚 Last abra installation log (/tmp/abra-install.log):"
|
|
||||||
cat /tmp/abra-install.log
|
|
||||||
else
|
|
||||||
echo "ℹ️ No abra installation log found at /tmp/abra-install.log"
|
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
echo "💡 To check if abra is in your PATH: which abra"
|
|
||||||
echo "💡 To check abra version: abra --version"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
help() {
|
help() {
|
||||||
echo "🚀 CODE CRISPIES Workshop Commands:"
|
echo "🚀 CODE CRISPIES Workshop Commands:"
|
||||||
echo ""
|
echo ""
|
||||||
echo "🏠 Local Development:"
|
echo "🏠 Local Development:"
|
||||||
echo " setup-traefik - Setup local Traefik proxy (REQUIRED FIRST!)"
|
echo " setup-traefik - Setup local proxy (REQUIRED FIRST!)"
|
||||||
echo " recipes - Show all available app recipes"
|
echo " recipes - Show all available apps"
|
||||||
echo " deploy <recipe> - Deploy app locally (e.g., deploy wordpress)"
|
echo " deploy <recipe> - Deploy app locally"
|
||||||
echo " browser [recipe] - Launch Firefox [to specific app]"
|
echo " browser [recipe] - Launch Firefox [to app]"
|
||||||
echo " desktop - Start GUI desktop session"
|
echo " desktop - Start GUI session"
|
||||||
echo " abra-status - Check the status of the abra setup service"
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "☁️ Cloud Access:"
|
echo "☁️ Cloud Access:"
|
||||||
echo " connect <name> - SSH to cloud server (e.g., connect hopper)"
|
echo " connect <name> - SSH to cloud server"
|
||||||
|
echo " Available: ${serverList}"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Available servers: ${builtins.concatStringsSep " " cloudServerNames}"
|
echo "🔍 Debug:"
|
||||||
|
echo " abra-status - Check setup service"
|
||||||
|
echo " docker service ls - List running services"
|
||||||
|
echo " systemctl status dnsmasq - Check DNS"
|
||||||
echo ""
|
echo ""
|
||||||
echo "📚 Learning Flow:"
|
echo "📚 Learning Flow:"
|
||||||
echo " 1. First time: setup-traefik"
|
echo " 1. setup-traefik"
|
||||||
echo " 2. Try local: recipes → deploy wordpress → browser wordpress"
|
echo " 2. deploy wordpress"
|
||||||
echo " 3. Try cloud: connect hopper → same abra commands"
|
echo " 3. browser wordpress"
|
||||||
echo ""
|
echo " 4. connect hopper"
|
||||||
echo "🔍 Debug Commands:"
|
|
||||||
echo " docker service ls - Check running services"
|
|
||||||
echo " dig @127.0.0.1 app.workshop.local - Test DNS resolution"
|
|
||||||
echo " systemctl status dnsmasq - Check DNS service"
|
|
||||||
echo ""
|
|
||||||
echo "💡 Tab completion available for deploy, browser, connect commands"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
'';
|
'';
|
||||||
};
|
|
||||||
|
|
||||||
|
# GUI Configuration
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
desktopManager.xfce.enable = true;
|
desktopManager.xfce.enable = true;
|
||||||
displayManager.lightdm.enable = true;
|
displayManager.lightdm.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Don't auto-start GUI, let user choose
|
|
||||||
systemd.user.services.workshop-welcome = {
|
|
||||||
wantedBy = [ "default.target" ];
|
|
||||||
script = ''
|
|
||||||
echo "Welcome! Run 'desktop' to start GUI session"
|
|
||||||
'';
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user