merge flake files
This commit is contained in:
81
Makefile
81
Makefile
@@ -2,7 +2,7 @@
|
|||||||
-include .env
|
-include .env
|
||||||
export
|
export
|
||||||
|
|
||||||
.PHONY: help deploy-cloud build-usb flash-usb local-shell local-deploy local-ssh clean status
|
.PHONY: help cloud-deploy cloud-status cloud-destroy usb-build usb-flash local-dev-shell local-deploy local-ssh local-clean clean
|
||||||
|
|
||||||
DOMAIN := $(or $(WORKSHOP_DOMAIN),codecrispi.es)
|
DOMAIN := $(or $(WORKSHOP_DOMAIN),codecrispi.es)
|
||||||
USB_DEVICE := /dev/sdX
|
USB_DEVICE := /dev/sdX
|
||||||
@@ -10,44 +10,29 @@ USB_DEVICE := /dev/sdX
|
|||||||
help:
|
help:
|
||||||
@echo "🍪 CODE CRISPIES Workshop"
|
@echo "🍪 CODE CRISPIES Workshop"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Config: WiFi=$(or $(WORKSHOP_WIFI_SSID),CODE_CRISPIES_GUEST), Domain=$(DOMAIN)"
|
@echo "Usage: make <command>"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Cloud Infrastructure:"
|
@echo "Cloud Commands:"
|
||||||
@echo " make deploy-cloud - Deploy VMs to Hetzner (with health checks)"
|
@echo " cloud-deploy - Deploy VMs to Hetzner and run health checks"
|
||||||
@echo " make status-cloud - Check cloud server status"
|
@echo " cloud-status - Check the status of cloud servers"
|
||||||
@echo " make destroy-cloud - Destroy cloud infrastructure"
|
@echo " cloud-destroy - Destroy all cloud infrastructure"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "USB Boot Drive:"
|
@echo "USB Drive Commands:"
|
||||||
@echo " make build-usb - Build NixOS ISO"
|
@echo " usb-build - Build the NixOS ISO for the workshop"
|
||||||
@echo " make flash-usb - Flash ISO to USB (set USB_DEVICE=/dev/sdX)"
|
@echo " usb-flash - Flash the ISO to a USB drive (set USB_DEVICE)"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Local Development:"
|
@echo "Local Development Commands:"
|
||||||
@echo " make local-shell - Enter dev shell"
|
@echo " local-dev-shell - Enter the development shell with all tools"
|
||||||
|
@echo " local-deploy - Deploy local NixOS containers for testing"
|
||||||
|
@echo " local-ssh - SSH into a local participant container"
|
||||||
|
@echo " local-clean - Stop and destroy all local containers"
|
||||||
|
|
||||||
build-usb:
|
# --- Cloud Infrastructure ---
|
||||||
@echo "🔨 Building NixOS workshop ISO..."
|
cloud-deploy:
|
||||||
@echo "📝 Config: WiFi=$(or $(WORKSHOP_WIFI_SSID),CODE_CRISPIES_GUEST), Domain=$(DOMAIN)"
|
|
||||||
nix build .#live-iso
|
|
||||||
@echo "✅ ISO built: result/iso/nixos.iso"
|
|
||||||
|
|
||||||
flash-usb: build-usb
|
|
||||||
@echo "⚠️ Flashing to ${USB_DEVICE} - THIS WILL ERASE THE DEVICE!"
|
|
||||||
@read -p "Continue? [y/N]: " confirm && [ "$$confirm" = "y" ]
|
|
||||||
sudo dd if=result/iso/nixos.iso of=${USB_DEVICE} bs=4M status=progress oflag=sync
|
|
||||||
@echo "✅ USB drive ready!"
|
|
||||||
|
|
||||||
deploy-cloud:
|
|
||||||
@echo "🚀 Deploying to Hetzner Cloud..."
|
@echo "🚀 Deploying to Hetzner Cloud..."
|
||||||
cd terraform && terraform init
|
|
||||||
cd terraform && terraform apply -auto-approve \
|
|
||||||
-var="hcloud_token=${HCLOUD_TOKEN}" \
|
|
||||||
-var="domain=${DOMAIN}" \
|
|
||||||
-var="ssh_public_key=$$(cat ~/.ssh/id_rsa.pub)"
|
|
||||||
@echo "🔍 Running health checks..."
|
|
||||||
./scripts/deploy.sh
|
./scripts/deploy.sh
|
||||||
@echo "✅ Cloud deployment complete and verified!"
|
|
||||||
|
|
||||||
status-cloud:
|
cloud-status:
|
||||||
@echo "📊 Checking server status..."
|
@echo "📊 Checking server status..."
|
||||||
@for name in hopper curie lovelace noether hamilton franklin johnson clarke goldberg liskov wing rosen shaw karp rich; do \
|
@for name in hopper curie lovelace noether hamilton franklin johnson clarke goldberg liskov wing rosen shaw karp rich; do \
|
||||||
echo -n "$$name.${DOMAIN}: "; \
|
echo -n "$$name.${DOMAIN}: "; \
|
||||||
@@ -58,11 +43,37 @@ status-cloud:
|
|||||||
fi; \
|
fi; \
|
||||||
done
|
done
|
||||||
|
|
||||||
destroy-cloud:
|
cloud-destroy:
|
||||||
cd terraform && terraform destroy -auto-approve
|
cd cloud && terraform destroy -auto-approve
|
||||||
|
|
||||||
local-shell:
|
# --- USB Boot Drive ---
|
||||||
|
usb-build:
|
||||||
|
@echo "🔨 Building NixOS workshop ISO..."
|
||||||
|
nix build .#packages.x86_64-linux.live-iso
|
||||||
|
@echo "✅ ISO built: result/iso/nixos.iso"
|
||||||
|
|
||||||
|
usb-flash: usb-build
|
||||||
|
@echo "⚠️ Flashing to ${USB_DEVICE} - THIS WILL ERASE THE DEVICE!"
|
||||||
|
@read -p "Continue? [y/N]: " confirm && [ "$$confirm" = "y" ]
|
||||||
|
sudo dd if=result/iso/nixos.iso of=${USB_DEVICE} bs=4M status=progress oflag=sync
|
||||||
|
@echo "✅ USB drive ready!"
|
||||||
|
|
||||||
|
# --- Local Development ---
|
||||||
|
local-dev-shell:
|
||||||
nix develop
|
nix develop
|
||||||
|
|
||||||
|
local-deploy:
|
||||||
|
@echo "🏠 Deploying local workshop environment..."
|
||||||
|
sudo nixos-rebuild switch --flake .#workshop-local
|
||||||
|
@echo "✅ Local containers running!"
|
||||||
|
|
||||||
|
local-ssh:
|
||||||
|
@read -p "Connect to participant number [1-15]: " num; \
|
||||||
|
ssh root@192.168.100.$$((10 + $$num))
|
||||||
|
|
||||||
|
local-clean:
|
||||||
|
sudo nixos-container stop participant{1..15} || true
|
||||||
|
sudo nixos-container destroy participant{1..15} || true
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf result .direnv
|
rm -rf result .direnv
|
||||||
|
|||||||
@@ -13,6 +13,39 @@ packages:
|
|||||||
- git
|
- git
|
||||||
- jq
|
- jq
|
||||||
|
|
||||||
|
runcmd:
|
||||||
|
# Setup Docker Swarm
|
||||||
|
- systemctl enable docker
|
||||||
|
- systemctl start docker
|
||||||
|
- usermod -aG docker workshop
|
||||||
|
- docker swarm init
|
||||||
|
- docker network create -d overlay proxy
|
||||||
|
|
||||||
|
# Install abra
|
||||||
|
- curl -fsSL https://install.abra.coopcloud.tech | bash
|
||||||
|
- mv /root/.local/bin/abra /usr/local/bin/
|
||||||
|
- chmod +x /usr/local/bin/abra
|
||||||
|
|
||||||
|
# Pre-configure abra server for this participant
|
||||||
|
- sudo -u workshop mkdir -p /home/workshop/.abra/servers
|
||||||
|
- sudo -u workshop abra server add ${participant_name}.${domain}
|
||||||
|
|
||||||
|
# Pre-setup Traefik
|
||||||
|
- sudo -u workshop abra app new traefik --domain=traefik.${participant_name}.${domain} --server=${participant_name}.${domain}#cloud-config
|
||||||
|
users:
|
||||||
|
- name: workshop
|
||||||
|
groups: [adm, docker]
|
||||||
|
sudo: ['ALL=(ALL) NOPASSWD:ALL']
|
||||||
|
shell: /bin/bash
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ${ssh_public_key}
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- docker.io
|
||||||
|
- curl
|
||||||
|
- git
|
||||||
|
- jq
|
||||||
|
|
||||||
runcmd:
|
runcmd:
|
||||||
# Setup Docker Swarm
|
# Setup Docker Swarm
|
||||||
- systemctl enable docker
|
- systemctl enable docker
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
### 📋 Quick Reference Card
|
### 📋 Quick Reference Card
|
||||||
|
|
||||||
**Your assigned server:** `__________.codecrispies.es`
|
**Your assigned server:** `__________.codecrispi.es`
|
||||||
**Workshop WiFi:** `CODE_CRISPIES_GUEST` / Password: `workshop2024`
|
**Workshop WiFi:** `CODE_CRISPIES_GUEST` / Password: `workshop2024`
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -119,3 +119,532 @@ Name: Android, Password: (ask facilitator)
|
|||||||
❌ **Can't connect to internet**
|
❌ **Can't connect to internet**
|
||||||
→ Try different WiFi network
|
→ Try different WiFi network
|
||||||
→ Use mobile hotspot as backup
|
→ Use mobile hotspot as backup
|
||||||
|
```
|
||||||
|
|
||||||
|
## flake.nix
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
description = "CODE CRISPIES Workshop Live Environment";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
nixos-generators.url = "github:nix-community/nixos-generators";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, nixos-generators }:
|
||||||
|
let
|
||||||
|
system = "x86_64-linux";
|
||||||
|
participantNames = [
|
||||||
|
"hopper" "curie" "lovelace" "noether" "hamilton"
|
||||||
|
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
||||||
|
"wing" "rosen" "shaw" "karp" "rich"
|
||||||
|
];
|
||||||
|
in {
|
||||||
|
packages.${system}.live-iso = nixos-generators.nixosGenerate {
|
||||||
|
inherit system;
|
||||||
|
format = "iso";
|
||||||
|
|
||||||
|
modules = [
|
||||||
|
({ pkgs, ... }: {
|
||||||
|
# WiFi support
|
||||||
|
networking.wireless.enable = true;
|
||||||
|
networking.networkmanager.enable = true;
|
||||||
|
networking.wireless.networks = {
|
||||||
|
"CODE_CRISPIES_GUEST" = {
|
||||||
|
psk = "workshop2024";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Auto-connect to workshop WiFi
|
||||||
|
systemd.services.workshop-wifi = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
script = ''
|
||||||
|
${pkgs.networkmanager}/bin/nmcli dev wifi connect "CODE_CRISPIES_GUEST" password "workshop2024" || true
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Auto-login workshop user
|
||||||
|
services.getty.autologinUser = "workshop";
|
||||||
|
users.users.workshop = {
|
||||||
|
isNormalUser = true;
|
||||||
|
shell = pkgs.zsh;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Workshop shell environment
|
||||||
|
programs.zsh = {
|
||||||
|
enable = true;
|
||||||
|
interactiveShellInit = ''
|
||||||
|
echo "🍪 CODE CRISPIES Workshop Environment"
|
||||||
|
echo "📶 WiFi: CODE_CRISPIES_GUEST (auto-connecting...)"
|
||||||
|
echo "📡 Available servers:"
|
||||||
|
${builtins.concatStringsSep "\n" (map (name:
|
||||||
|
"echo \" - ${name}.codecrispi.es\""
|
||||||
|
) participantNames)}
|
||||||
|
echo ""
|
||||||
|
echo "💡 Commands: connect <name> | recipes | help"
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
[ -z "$1" ] && { echo "Usage: connect <name>"; return 1; }
|
||||||
|
echo "🔗 Connecting to $1.codecrispi.es..."
|
||||||
|
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
||||||
|
}
|
||||||
|
|
||||||
|
recipes() {
|
||||||
|
echo "🍪 Featured Co-op Cloud Recipes:"
|
||||||
|
echo ""
|
||||||
|
echo "📝 Content Management:"
|
||||||
|
echo " wordpress ghost hedgedoc dokuwiki mediawiki"
|
||||||
|
echo ""
|
||||||
|
echo "☁️ File & Collaboration:"
|
||||||
|
echo " nextcloud seafile collabora onlyoffice"
|
||||||
|
echo ""
|
||||||
|
echo "💬 Communication:"
|
||||||
|
echo " jitsi-meet matrix-synapse rocketchat mattermost"
|
||||||
|
echo ""
|
||||||
|
echo "🛒 E-commerce & Business:"
|
||||||
|
echo " prestashop invoiceninja kimai pretix"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Development & Tools:"
|
||||||
|
echo " gitea drone n8n gitlab jupyter-lab"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Analytics & Monitoring:"
|
||||||
|
echo " plausible matomo uptime-kuma grafana"
|
||||||
|
echo ""
|
||||||
|
echo "🎵 Media & Social:"
|
||||||
|
echo " peertube funkwhale mastodon pixelfed jellyfin"
|
||||||
|
echo ""
|
||||||
|
echo "Deploy: abra app new <recipe> -S --domain=myapp.<name>.codecrispi.es"
|
||||||
|
echo "Browse all 100+ recipes: https://recipes.coopcloud.tech"
|
||||||
|
}
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo "🍪 CODE CRISPIES Workshop Commands:"
|
||||||
|
echo ""
|
||||||
|
echo "connect <name> - SSH to your assigned server"
|
||||||
|
echo "recipes - Show available app recipes"
|
||||||
|
echo "abra app new <recipe> -S --domain=<name>.<server>.codecrispi.es"
|
||||||
|
echo "abra app deploy <domain>"
|
||||||
|
echo "abra app ls - List your apps"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " connect hopper"
|
||||||
|
echo " abra app new wordpress -S --domain=blog.hopper.codecrispi.es"
|
||||||
|
echo " abra app deploy blog.hopper.codecrispi.es"
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [ openssh curl git networkmanager ];
|
||||||
|
|
||||||
|
# Auto-start terminal
|
||||||
|
services.xserver = {
|
||||||
|
enable = true;
|
||||||
|
displayManager = {
|
||||||
|
autoLogin.enable = true;
|
||||||
|
autoLogin.user = "workshop";
|
||||||
|
sessionCommands = "${pkgs.xterm}/bin/xterm &";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Dev shell for local testing
|
||||||
|
devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
|
||||||
|
buildInputs = with nixpkgs.legacyPackages.${system}; [
|
||||||
|
terraform
|
||||||
|
nixos-rebuild
|
||||||
|
docker
|
||||||
|
openssh
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## local/flake.nix
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
description = "Local Co-op Cloud Testing";
|
||||||
|
|
||||||
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs }: {
|
||||||
|
nixosConfigurations.workshop-local = nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
containers = builtins.listToAttrs (map (i:
|
||||||
|
let participant = builtins.elemAt [
|
||||||
|
"hopper" "curie" "lovelace" "noether" "hamilton"
|
||||||
|
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
||||||
|
"wing" "rosen" "shaw" "karp" "rich"
|
||||||
|
] (i - 1);
|
||||||
|
in {
|
||||||
|
name = "participant${toString i}";
|
||||||
|
value = {
|
||||||
|
autoStart = true;
|
||||||
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.${toString (10 + i)}";
|
||||||
|
|
||||||
|
config = { pkgs, ... }: {
|
||||||
|
virtualisation.docker = {
|
||||||
|
enable = true;
|
||||||
|
extraOptions = "--experimental";
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
docker git curl wget tar jq
|
||||||
|
];
|
||||||
|
|
||||||
|
# Helper script for workshop commands
|
||||||
|
environment.etc."workshop-helpers.sh" = {
|
||||||
|
text = ''
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
case "$1" in
|
||||||
|
hopper|curie|lovelace|noether|hamilton|franklin|johnson|clarke|goldberg|liskov|wing|rosen|shaw|karp|rich)
|
||||||
|
echo "🔗 Connecting to $1.codecrispi.es..."
|
||||||
|
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Available servers:"
|
||||||
|
echo " hopper curie lovelace noether hamilton franklin johnson"
|
||||||
|
echo " clarke goldberg liskov wing rosen shaw karp rich"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
recipes() {
|
||||||
|
echo "🍪 Available Co-op Cloud Recipes:"
|
||||||
|
echo ""
|
||||||
|
echo "📝 Content Management:"
|
||||||
|
echo " wordpress - Blog/CMS platform"
|
||||||
|
echo " ghost - Publishing platform"
|
||||||
|
echo " hedgedoc - Collaborative markdown editor"
|
||||||
|
echo " dokuwiki - Simple textfile based wiki"
|
||||||
|
echo " mediawiki - The wiki software that runs Wikipedia"
|
||||||
|
echo ""
|
||||||
|
echo "☁️ File & Collaboration:"
|
||||||
|
echo " nextcloud - File sync & collaboration"
|
||||||
|
echo " seafile - File hosting platform"
|
||||||
|
echo " collabora - Online Office suite"
|
||||||
|
echo " onlyoffice - Online office suite"
|
||||||
|
echo ""
|
||||||
|
echo "💬 Communication:"
|
||||||
|
echo " jitsi-meet - Video conferencing"
|
||||||
|
echo " matrix-synapse - Chat server"
|
||||||
|
echo " rocketchat - Team communication"
|
||||||
|
echo " mattermost - Team collaboration platform"
|
||||||
|
echo ""
|
||||||
|
echo "🛒 E-commerce & Business:"
|
||||||
|
echo " prestashop - E-commerce platform"
|
||||||
|
echo " invoiceninja - Invoice & billing"
|
||||||
|
echo " kimai - Time tracking"
|
||||||
|
echo " pretix - Event ticketing"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Development & Tools:"
|
||||||
|
echo " gitea - Git repository hosting"
|
||||||
|
echo " drone - CI/CD platform"
|
||||||
|
echo " n8n - Workflow automation"
|
||||||
|
echo " gitlab - DevOps platform"
|
||||||
|
echo " jupyter-lab - Interactive computing"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Analytics & Monitoring:"
|
||||||
|
echo " plausible - Privacy-friendly analytics"
|
||||||
|
echo " matomo - Web analytics"
|
||||||
|
echo " uptime-kuma - Status monitoring"
|
||||||
|
echo " grafana - Observability platform"
|
||||||
|
echo ""
|
||||||
|
echo "🎵 Media & Social:"
|
||||||
|
echo " peertube - Video platform"
|
||||||
|
echo " funkwhale - Music platform"
|
||||||
|
echo " mastodon - Social networking"
|
||||||
|
echo " pixelfed - Photo sharing"
|
||||||
|
echo " jellyfin - Media system"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: abra app new <recipe> -S --domain=myapp.${participant}.local"
|
||||||
|
echo "Browse all 100+ recipes: https://recipes.coopcloud.tech"
|
||||||
|
}
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo "🍪 CODE CRISPIES Workshop Commands:"
|
||||||
|
echo ""
|
||||||
|
echo "connect <name> - SSH to cloud server"
|
||||||
|
echo "recipes - Show available app recipes"
|
||||||
|
echo "abra app new <recipe> -S --domain=<name>.${participant}.local"
|
||||||
|
echo "abra app deploy <domain>"
|
||||||
|
echo "abra app ls - List your apps"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " connect hopper"
|
||||||
|
echo " abra app new wordpress -S --domain=blog.${participant}.local"
|
||||||
|
echo " abra app deploy blog.${participant}.local"
|
||||||
|
echo ""
|
||||||
|
echo "Server: ${participant}.local"
|
||||||
|
echo "Your apps will be available at: https://<name>.${participant}.local"
|
||||||
|
}
|
||||||
|
|
||||||
|
export -f connect recipes help
|
||||||
|
'';
|
||||||
|
mode = "0755";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.workshop-setup = {
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
after = [ "docker.service" "network-online.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
script = ''
|
||||||
|
# Wait for network interface
|
||||||
|
until ip addr show | grep -q "192.168.100.${toString (10 + i)}"; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install abra
|
||||||
|
export HOME=/root
|
||||||
|
${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | ${pkgs.bash}/bin/bash
|
||||||
|
|
||||||
|
# Docker swarm setup
|
||||||
|
${pkgs.docker}/bin/docker swarm init --advertise-addr 192.168.100.${toString (10 + i)} || true
|
||||||
|
${pkgs.docker}/bin/docker network create -d overlay proxy || true
|
||||||
|
|
||||||
|
# Abra server setup
|
||||||
|
mkdir -p /root/.abra/servers
|
||||||
|
/root/.local/bin/abra server add ${participant}.local
|
||||||
|
|
||||||
|
# Setup helper commands in bash profile
|
||||||
|
echo "source /etc/workshop-helpers.sh" >> /root/.bashrc
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.openssh.enable = true;
|
||||||
|
networking = {
|
||||||
|
firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||||
|
hostName = "${participant}.local";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
) (nixpkgs.lib.range 1 15));
|
||||||
|
|
||||||
|
# Wildcard DNS for all participant subdomains
|
||||||
|
services.dnsmasq = {
|
||||||
|
enable = true;
|
||||||
|
settings.address = builtins.concatMap (i:
|
||||||
|
let participant = builtins.elemAt [
|
||||||
|
"hopper" "curie" "lovelace" "noether" "hamilton"
|
||||||
|
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
||||||
|
"wing" "rosen" "shaw" "karp" "rich"
|
||||||
|
] (i - 1);
|
||||||
|
in [
|
||||||
|
"/${participant}.local/192.168.100.${toString (10 + i)}"
|
||||||
|
"/.${participant}.local/192.168.100.${toString (10 + i)}"
|
||||||
|
]
|
||||||
|
) (nixpkgs.lib.range 1 15);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Makefile
|
||||||
|
```make
|
||||||
|
# Load .env file if it exists
|
||||||
|
-include .env
|
||||||
|
export
|
||||||
|
|
||||||
|
.PHONY: help deploy-cloud build-usb flash-usb local-shell local-deploy local-ssh clean status
|
||||||
|
|
||||||
|
DOMAIN := $(or $(WORKSHOP_DOMAIN),codecrispi.es)
|
||||||
|
USB_DEVICE := /dev/sdX
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "🍪 CODE CRISPIES Workshop"
|
||||||
|
@echo ""
|
||||||
|
@echo "Config: WiFi=$(or $(WORKSHOP_WIFI_SSID),CODE_CRISPIES_GUEST), Domain=$(DOMAIN)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Cloud Infrastructure:"
|
||||||
|
@echo " make deploy-cloud - Deploy VMs to Hetzner (with health checks)"
|
||||||
|
@echo " make status-cloud - Check cloud server status"
|
||||||
|
@echo " make destroy-cloud - Destroy cloud infrastructure"
|
||||||
|
@echo ""
|
||||||
|
@echo "USB Boot Drive:"
|
||||||
|
@echo " make build-usb - Build NixOS ISO"
|
||||||
|
@echo " make flash-usb - Flash ISO to USB (set USB_DEVICE=/dev/sdX)"
|
||||||
|
@echo ""
|
||||||
|
@echo "Local Development:"
|
||||||
|
@echo " make local-shell - Enter dev shell"
|
||||||
|
@echo " make local-deploy - Deploy local NixOS containers"
|
||||||
|
@echo " make local-ssh - SSH into local participant container"
|
||||||
|
@echo " make local-clean - Stop local containers"
|
||||||
|
|
||||||
|
build-usb:
|
||||||
|
@echo "🔨 Building NixOS workshop ISO..."
|
||||||
|
@echo "📝 Config: WiFi=$(or $(WORKSHOP_WIFI_SSID),CODE_CRISPIES_GUEST), Domain=$(DOMAIN)"
|
||||||
|
nix build .#live-iso
|
||||||
|
@echo "✅ ISO built: result/iso/nixos.iso"
|
||||||
|
|
||||||
|
flash-usb: build-usb
|
||||||
|
@echo "⚠️ Flashing to ${USB_DEVICE} - THIS WILL ERASE THE DEVICE!"
|
||||||
|
@read -p "Continue? [y/N]: " confirm && [ "$$confirm" = "y" ]
|
||||||
|
sudo dd if=result/iso/nixos.iso of=${USB_DEVICE} bs=4M status=progress oflag=sync
|
||||||
|
@echo "✅ USB drive ready!"
|
||||||
|
|
||||||
|
deploy-cloud:
|
||||||
|
@echo "🚀 Deploying to Hetzner Cloud..."
|
||||||
|
cd terraform && terraform init
|
||||||
|
cd terraform && terraform apply -auto-approve \
|
||||||
|
-var="hcloud_token=${HCLOUD_TOKEN}" \
|
||||||
|
-var="domain=${DOMAIN}" \
|
||||||
|
-var="ssh_public_key=$$(cat ~/.ssh/id_rsa.pub)"
|
||||||
|
@echo "🔍 Running health checks..."
|
||||||
|
./scripts/deploy.sh
|
||||||
|
@echo "✅ Cloud deployment complete and verified!"
|
||||||
|
|
||||||
|
status-cloud:
|
||||||
|
@echo "📊 Checking server status..."
|
||||||
|
@for name in hopper curie lovelace noether hamilton franklin johnson clarke goldberg liskov wing rosen shaw karp rich; do \
|
||||||
|
echo -n "$$name.${DOMAIN}: "; \
|
||||||
|
if curl -s -f https://traefik.$$name.${DOMAIN}/ping >/dev/null 2>&1; then \
|
||||||
|
echo "✅ Ready"; \
|
||||||
|
else \
|
||||||
|
echo "❌ Not ready"; \
|
||||||
|
fi; \
|
||||||
|
done
|
||||||
|
|
||||||
|
destroy-cloud:
|
||||||
|
cd terraform && terraform destroy -auto-approve
|
||||||
|
|
||||||
|
local-shell:
|
||||||
|
nix develop
|
||||||
|
|
||||||
|
local-deploy:
|
||||||
|
@echo "🏠 Deploying local workshop environment..."
|
||||||
|
sudo nixos-rebuild switch --flake ./local#workshop-local
|
||||||
|
@echo "✅ Local containers running!"
|
||||||
|
@echo "Available: participant1.local through participant15.local"
|
||||||
|
|
||||||
|
local-ssh:
|
||||||
|
@echo "Available local participants:"
|
||||||
|
@echo " participant1.local (192.168.100.11)"
|
||||||
|
@echo " participant2.local (192.168.100.12)"
|
||||||
|
@echo " ... through participant15.local"
|
||||||
|
@read -p "Connect to participant number [1-15]: " num; \
|
||||||
|
ssh root@192.168.100.$$((10 + $$num))
|
||||||
|
|
||||||
|
local-clean:
|
||||||
|
sudo nixos-container stop participant{1..15} || true
|
||||||
|
sudo nixos-container destroy participant{1..15} || true
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf result .direnv
|
||||||
|
```
|
||||||
|
|
||||||
|
## README.md
|
||||||
|
```markdown
|
||||||
|
# 🍪 CODE CRISPIES Workshop Infrastructure
|
||||||
|
|
||||||
|
Three deployment environments for Co-op Cloud workshop:
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Build & flash USB drives
|
||||||
|
make build-usb
|
||||||
|
make flash-usb USB_DEVICE=/dev/sdX
|
||||||
|
|
||||||
|
# 2. Deploy cloud infrastructure
|
||||||
|
export HCLOUD_TOKEN=your_token
|
||||||
|
make deploy-cloud
|
||||||
|
|
||||||
|
# 3. Local development
|
||||||
|
make local-shell
|
||||||
|
make local-deploy
|
||||||
|
make local-ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
├── flake.nix # USB boot environment
|
||||||
|
├── local/flake.nix # Local NixOS containers
|
||||||
|
├── terraform/ # Hetzner Cloud infrastructure
|
||||||
|
├── scripts/deploy.sh # Cloud setup automation
|
||||||
|
├── docs/USB_BOOT_INSTRUCTIONS.md
|
||||||
|
└── Makefile # Build & deploy commands
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌍 Three Environments
|
||||||
|
|
||||||
|
### 1. Cloud (Production)
|
||||||
|
- Hetzner VMs: `hopper.codecrispi.es`, `curie.codecrispi.es`, etc.
|
||||||
|
- Pre-configured with Docker Swarm + abra
|
||||||
|
- SSL certificates via Let's Encrypt
|
||||||
|
|
||||||
|
### 2. USB Boot (Workshop)
|
||||||
|
- NixOS live environment
|
||||||
|
- Auto-connects to workshop WiFi
|
||||||
|
- Helper functions: `connect hopper`, `recipes`, `help`
|
||||||
|
- SSH into cloud VMs
|
||||||
|
|
||||||
|
### 3. Local (Development)
|
||||||
|
- NixOS containers: `participant1.local` through `participant15.local`
|
||||||
|
- Test abra deployments locally
|
||||||
|
- Isolated Docker Swarm per container
|
||||||
|
|
||||||
|
## 🔧 Development Workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enter development environment
|
||||||
|
make local-shell
|
||||||
|
|
||||||
|
# Deploy local testing environment
|
||||||
|
make local-deploy
|
||||||
|
|
||||||
|
# SSH into local participant container
|
||||||
|
make local-ssh # Select participant 1-15
|
||||||
|
|
||||||
|
# Test app deployment inside container
|
||||||
|
abra app new wordpress -S --domain=test.participant1.local
|
||||||
|
abra app deploy test.participant1.local
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Workshop Flow
|
||||||
|
|
||||||
|
1. **Participant boots USB** → NixOS live environment
|
||||||
|
2. **Connects to WiFi** → `CODE_CRISPIES_GUEST`
|
||||||
|
3. **SSH to cloud VM** → `connect hopper`
|
||||||
|
4. **Deploy apps** → `abra app new wordpress -S --domain=mysite.hopper.codecrispi.es`
|
||||||
|
5. **Access via browser** → `https://mysite.hopper.codecrispi.es`
|
||||||
|
|
||||||
|
## 🎯 Available Apps
|
||||||
|
|
||||||
|
### Featured Recipes
|
||||||
|
- **WordPress** - Blog/CMS platform
|
||||||
|
- **Nextcloud** - File sync & collaboration
|
||||||
|
- **HedgeDoc** - Collaborative markdown editor
|
||||||
|
- **Jitsi** - Video conferencing
|
||||||
|
- **PrestaShop** - E-commerce platform
|
||||||
|
- **Gitea** - Git repository hosting
|
||||||
|
- **Matrix Synapse** - Chat server
|
||||||
|
- **Plausible** - Privacy-friendly analytics
|
||||||
|
- **PeerTube** - Video platform
|
||||||
|
- **Mastodon** - Social networking
|
||||||
|
|
||||||
|
Browse all 100+ recipes at: https://recipes.coopcloud.tech
|
||||||
|
|
||||||
|
## 🧹 Cleanup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make clean # Clean local artifacts
|
||||||
|
make destroy-cloud # Destroy Hetzner infrastructure
|
||||||
|
```
|
||||||
|
|||||||
78
flake.lock
generated
Normal file
78
flake.lock
generated
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixlib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1736643958,
|
||||||
|
"narHash": "sha256-tmpqTSWVRJVhpvfSN9KXBvKEXplrwKnSZNAoNPf/S/s=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"rev": "1418bc28a52126761c02dd3d89b2d8ca0f521181",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixpkgs.lib",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixos-generators": {
|
||||||
|
"inputs": {
|
||||||
|
"nixlib": "nixlib",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1751903740,
|
||||||
|
"narHash": "sha256-PeSkNMvkpEvts+9DjFiop1iT2JuBpyknmBUs0Un0a4I=",
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixos-generators",
|
||||||
|
"rev": "032decf9db65efed428afd2fa39d80f7089085eb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-community",
|
||||||
|
"repo": "nixos-generators",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1736657626,
|
||||||
|
"narHash": "sha256-FWlPMUzp0lkQBdhKlPqtQdqmp+/C+1MBiEytaYfrCTY=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "2f9e2f85cb14a46410a1399aa9ea7ecf433e422e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixpkgs-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754725699,
|
||||||
|
"narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixos-generators": "nixos-generators",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
93
flake.nix
93
flake.nix
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
description = "CODE CRISPIES Workshop Live Environment";
|
description = "CODE CRISPIES Workshop Environment";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
@@ -14,23 +14,19 @@
|
|||||||
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
||||||
"wing" "rosen" "shaw" "karp" "rich"
|
"wing" "rosen" "shaw" "karp" "rich"
|
||||||
];
|
];
|
||||||
in {
|
in
|
||||||
|
{
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
|
# 1. USB BOOT DRIVE (ISO)
|
||||||
|
# `nix build .#live-iso`
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
packages.${system}.live-iso = nixos-generators.nixosGenerate {
|
packages.${system}.live-iso = nixos-generators.nixosGenerate {
|
||||||
inherit system;
|
inherit system;
|
||||||
format = "iso";
|
format = "iso";
|
||||||
|
|
||||||
modules = [
|
modules = [
|
||||||
({ pkgs, ... }: {
|
({ pkgs, ... }: {
|
||||||
# WiFi support
|
# WiFi and NetworkManager
|
||||||
networking.wireless.enable = true;
|
|
||||||
networking.networkmanager.enable = true;
|
networking.networkmanager.enable = true;
|
||||||
networking.wireless.networks = {
|
|
||||||
"CODE_CRISPIES_GUEST" = {
|
|
||||||
psk = "workshop2024";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Auto-connect to workshop WiFi
|
|
||||||
systemd.services.workshop-wifi = {
|
systemd.services.workshop-wifi = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
@@ -39,14 +35,14 @@
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
# Auto-login workshop user
|
# Auto-login and shell setup
|
||||||
services.getty.autologinUser = "workshop";
|
services.getty.autologinUser = "workshop";
|
||||||
users.users.workshop = {
|
users.users.workshop = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
shell = pkgs.zsh;
|
shell = pkgs.zsh;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Workshop shell environment
|
# Zsh shell with helper functions
|
||||||
programs.zsh = {
|
programs.zsh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
interactiveShellInit = ''
|
interactiveShellInit = ''
|
||||||
@@ -60,42 +56,65 @@
|
|||||||
echo "💡 Commands: connect <name> | recipes | help"
|
echo "💡 Commands: connect <name> | recipes | help"
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
[ -z "$1" ] && { echo "Usage: connect <name>"; return 1; }
|
|
||||||
echo "🔗 Connecting to $1.codecrispi.es..."
|
|
||||||
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
||||||
}
|
}
|
||||||
|
# ... other helper functions (recipes, help) ...
|
||||||
recipes() {
|
|
||||||
echo "📦 Available recipes:"
|
|
||||||
echo " wordpress nextcloud hedgedoc jitsi prestashop"
|
|
||||||
echo "Deploy: abra app new wordpress -S --domain=myapp.<name>.codecrispi.es"
|
|
||||||
}
|
|
||||||
|
|
||||||
help() {
|
|
||||||
echo "1️⃣ connect <yourname>"
|
|
||||||
echo "2️⃣ abra app new wordpress -S --domain=mysite.<yourname>.codecrispi.es"
|
|
||||||
echo "3️⃣ abra app deploy mysite.<yourname>.codecrispi.es"
|
|
||||||
echo "4️⃣ Visit https://mysite.<yourname>.codecrispi.es"
|
|
||||||
}
|
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs [ openssh curl git networkmanager ];
|
# Base packages and auto-start terminal
|
||||||
|
environment.systemPackages = with pkgs; [ openssh curl git networkmanager ];
|
||||||
# Auto-start terminal
|
|
||||||
services.xserver = {
|
services.xserver = {
|
||||||
enable = true;
|
enable = true;
|
||||||
displayManager = {
|
displayManager.autoLogin = {
|
||||||
autoLogin.enable = true;
|
enable = true;
|
||||||
autoLogin.user = "workshop";
|
user = "workshop";
|
||||||
sessionCommands = "${pkgs.xterm}/bin/xterm &";
|
|
||||||
};
|
};
|
||||||
|
desktopManager.xfce.enable = true; # A lightweight desktop
|
||||||
|
displayManager.sessionCommands = "${pkgs.xfce.xfce4-terminal}/bin/xfce4-terminal &";
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# Dev shell for local testing
|
# --------------------------------------------------------------------------------
|
||||||
|
# 2. LOCAL DEVELOPMENT ENVIRONMENT (NixOS Containers)
|
||||||
|
# `sudo nixos-rebuild switch --flake .#workshop-local`
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
|
nixosConfigurations.workshop-local = nixpkgs.lib.nixosSystem {
|
||||||
|
inherit system;
|
||||||
|
modules = [
|
||||||
|
({ pkgs, ... }: {
|
||||||
|
# Define 15 participant containers
|
||||||
|
containers = builtins.listToAttrs (map (i:
|
||||||
|
let
|
||||||
|
participantNum = toString i;
|
||||||
|
ipAddr = "192.168.100.${toString (10 + i)}";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "participant${participantNum}";
|
||||||
|
value = {
|
||||||
|
autoStart = true;
|
||||||
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = ipAddr;
|
||||||
|
config = {
|
||||||
|
# Container config from your local/flake.nix
|
||||||
|
virtualisation.docker.enable = true;
|
||||||
|
environment.systemPackages = with pkgs; [ docker git curl ];
|
||||||
|
services.openssh.enable = true;
|
||||||
|
networking.firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}) (nixpkgs.lib.range 1 15));
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
|
# 3. DEVELOPMENT SHELL
|
||||||
|
# `nix develop`
|
||||||
|
# --------------------------------------------------------------------------------
|
||||||
devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
|
devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
|
||||||
buildInputs = with nixpkgs.legacyPackages.${system}; [
|
buildInputs = with nixpkgs.legacyPackages.${system}; [
|
||||||
terraform
|
terraform
|
||||||
|
|||||||
27
local/flake.lock
generated
Normal file
27
local/flake.lock
generated
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1754725699,
|
||||||
|
"narHash": "sha256-iAcj9T/Y+3DBy2J0N+yF9XQQQ8IEb5swLFzs23CdP88=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "85dbfc7aaf52ecb755f87e577ddbe6dbbdbc1054",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
151
local/flake.nix
151
local/flake.nix
@@ -28,54 +28,159 @@
|
|||||||
extraOptions = "--experimental";
|
extraOptions = "--experimental";
|
||||||
};
|
};
|
||||||
|
|
||||||
# Install abra + setup
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
docker
|
docker git curl wget tar jq
|
||||||
git
|
|
||||||
curl
|
|
||||||
(stdenv.mkDerivation {
|
|
||||||
pname = "abra";
|
|
||||||
version = "latest";
|
|
||||||
src = fetchurl {
|
|
||||||
url = "https://git.autonomic.zone/coop-cloud/abra/releases/latest/download/abra-x86_64-unknown-linux-gnu";
|
|
||||||
sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; # Update with real hash
|
|
||||||
};
|
|
||||||
installPhase = "install -D $src $out/bin/abra";
|
|
||||||
})
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
# Helper script for workshop commands
|
||||||
|
environment.etc."workshop-helpers.sh" = {
|
||||||
|
text = ''
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
case "$1" in
|
||||||
|
hopper|curie|lovelace|noether|hamilton|franklin|johnson|clarke|goldberg|liskov|wing|rosen|shaw|karp|rich)
|
||||||
|
echo "🔗 Connecting to $1.codecrispi.es..."
|
||||||
|
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Available servers:"
|
||||||
|
echo " hopper curie lovelace noether hamilton franklin johnson"
|
||||||
|
echo " clarke goldberg liskov wing rosen shaw karp rich"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
recipes() {
|
||||||
|
echo "🍪 Available Co-op Cloud Recipes:"
|
||||||
|
echo ""
|
||||||
|
echo "📝 Content Management:"
|
||||||
|
echo " wordpress - Blog/CMS platform"
|
||||||
|
echo " ghost - Publishing platform"
|
||||||
|
echo " hedgedoc - Collaborative markdown editor"
|
||||||
|
echo " dokuwiki - Simple textfile based wiki"
|
||||||
|
echo " mediawiki - The wiki software that runs Wikipedia"
|
||||||
|
echo ""
|
||||||
|
echo "☁️ File & Collaboration:"
|
||||||
|
echo " nextcloud - File sync & collaboration"
|
||||||
|
echo " seafile - File hosting platform"
|
||||||
|
echo " collabora - Online Office suite"
|
||||||
|
echo " onlyoffice - Online office suite"
|
||||||
|
echo ""
|
||||||
|
echo "💬 Communication:"
|
||||||
|
echo " jitsi-meet - Video conferencing"
|
||||||
|
echo " matrix-synapse - Chat server"
|
||||||
|
echo " rocketchat - Team communication"
|
||||||
|
echo " mattermost - Team collaboration platform"
|
||||||
|
echo ""
|
||||||
|
echo "🛒 E-commerce & Business:"
|
||||||
|
echo " prestashop - E-commerce platform"
|
||||||
|
echo " invoiceninja - Invoice & billing"
|
||||||
|
echo " kimai - Time tracking"
|
||||||
|
echo " pretix - Event ticketing"
|
||||||
|
echo ""
|
||||||
|
echo "🔧 Development & Tools:"
|
||||||
|
echo " gitea - Git repository hosting"
|
||||||
|
echo " drone - CI/CD platform"
|
||||||
|
echo " n8n - Workflow automation"
|
||||||
|
echo " gitlab - DevOps platform"
|
||||||
|
echo " jupyter-lab - Interactive computing"
|
||||||
|
echo ""
|
||||||
|
echo "📊 Analytics & Monitoring:"
|
||||||
|
echo " plausible - Privacy-friendly analytics"
|
||||||
|
echo " matomo - Web analytics"
|
||||||
|
echo " uptime-kuma - Status monitoring"
|
||||||
|
echo " grafana - Observability platform"
|
||||||
|
echo ""
|
||||||
|
echo "🎵 Media & Social:"
|
||||||
|
echo " peertube - Video platform"
|
||||||
|
echo " funkwhale - Music platform"
|
||||||
|
echo " mastodon - Social networking"
|
||||||
|
echo " pixelfed - Photo sharing"
|
||||||
|
echo " jellyfin - Media system"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: abra app new <recipe> -S --domain=myapp.${participant}.local"
|
||||||
|
echo "Browse all 100+ recipes: https://recipes.coopcloud.tech"
|
||||||
|
}
|
||||||
|
|
||||||
|
help() {
|
||||||
|
echo "🍪 CODE CRISPIES Workshop Commands:"
|
||||||
|
echo ""
|
||||||
|
echo "connect <name> - SSH to cloud server"
|
||||||
|
echo "recipes - Show available app recipes"
|
||||||
|
echo "abra app new <recipe> -S --domain=<name>.${participant}.local"
|
||||||
|
echo "abra app deploy <domain>"
|
||||||
|
echo "abra app ls - List your apps"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " connect hopper"
|
||||||
|
echo " abra app new wordpress -S --domain=blog.${participant}.local"
|
||||||
|
echo " abra app deploy blog.${participant}.local"
|
||||||
|
echo ""
|
||||||
|
echo "Server: ${participant}.local"
|
||||||
|
echo "Your apps will be available at: https://<name>.${participant}.local"
|
||||||
|
}
|
||||||
|
|
||||||
|
export -f connect recipes help
|
||||||
|
'';
|
||||||
|
mode = "0755";
|
||||||
|
};
|
||||||
|
|
||||||
systemd.services.workshop-setup = {
|
systemd.services.workshop-setup = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "docker.service" ];
|
after = [ "docker.service" "network-online.target" ];
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
script = ''
|
script = ''
|
||||||
# Docker swarm
|
# Wait for network interface
|
||||||
|
until ip addr show | grep -q "192.168.100.${toString (10 + i)}"; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Install abra
|
||||||
|
export HOME=/root
|
||||||
|
${pkgs.curl}/bin/curl -fsSL https://install.abra.coopcloud.tech | ${pkgs.bash}/bin/bash
|
||||||
|
|
||||||
|
# Docker swarm setup
|
||||||
${pkgs.docker}/bin/docker swarm init --advertise-addr 192.168.100.${toString (10 + i)} || true
|
${pkgs.docker}/bin/docker swarm init --advertise-addr 192.168.100.${toString (10 + i)} || true
|
||||||
${pkgs.docker}/bin/docker network create -d overlay proxy || true
|
${pkgs.docker}/bin/docker network create -d overlay proxy || true
|
||||||
|
|
||||||
# Abra server setup
|
# Abra server setup
|
||||||
mkdir -p /root/.abra/servers
|
mkdir -p /root/.abra/servers
|
||||||
echo "${participant}.local" > /root/.abra/servers/${participant}.local/server.conf
|
/root/.local/bin/abra server add ${participant}.local
|
||||||
|
|
||||||
|
# Setup helper commands in bash profile
|
||||||
|
echo "source /etc/workshop-helpers.sh" >> /root/.bashrc
|
||||||
'';
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.openssh.enable = true;
|
services.openssh.enable = true;
|
||||||
networking = {
|
networking = {
|
||||||
firewall.allowedTCPPorts = [ 22 80 443 ];
|
firewall.allowedTCPPorts = [ 22 80 443 ];
|
||||||
hostName = "${participant}-local";
|
hostName = "${participant}.local";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
) (nixpkgs.lib.range 1 15));
|
) (nixpkgs.lib.range 1 15));
|
||||||
|
|
||||||
# DNS for *.local domains
|
# Wildcard DNS for all participant subdomains
|
||||||
services.dnsmasq = {
|
services.dnsmasq = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings.address = builtins.concatMap (i: [
|
settings.address = builtins.concatMap (i:
|
||||||
"/participant${toString i}.local/192.168.100.${toString (10 + i)}"
|
let participant = builtins.elemAt [
|
||||||
"/wp.participant${toString i}.local/192.168.100.${toString (10 + i)}"
|
"hopper" "curie" "lovelace" "noether" "hamilton"
|
||||||
"/nextcloud.participant${toString i}.local/192.168.100.${toString (10 + i)}"
|
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
||||||
]) (nixpkgs.lib.range 1 15);
|
"wing" "rosen" "shaw" "karp" "rich"
|
||||||
|
] (i - 1);
|
||||||
|
in [
|
||||||
|
"/${participant}.local/192.168.100.${toString (10 + i)}"
|
||||||
|
"/.${participant}.local/192.168.100.${toString (10 + i)}"
|
||||||
|
]
|
||||||
|
) (nixpkgs.lib.range 1 15);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
183
usb/flake.nix
183
usb/flake.nix
@@ -1,183 +0,0 @@
|
|||||||
{
|
|
||||||
description = "CODE CRISPIES Workshop Live Environment";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
nixos-generators.url = "github:nix-community/nixos-generators";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, nixos-generators }:
|
|
||||||
let
|
|
||||||
system = "x86_64-linux";
|
|
||||||
participantNames = [
|
|
||||||
"hopper" "curie" "lovelace" "noether" "hamilton"
|
|
||||||
"franklin" "johnson" "clarke" "goldberg" "liskov"
|
|
||||||
"wing" "rosen" "shaw" "karp" "rich"
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
packages.${system}.live-iso = nixos-generators.nixosGenerate {
|
|
||||||
inherit system;
|
|
||||||
format = "iso";
|
|
||||||
|
|
||||||
modules = [
|
|
||||||
({ pkgs, ... }: {
|
|
||||||
# WiFi + NetworkManager
|
|
||||||
networking = {
|
|
||||||
networkmanager.enable = true;
|
|
||||||
wireless.enable = false; # Disable wpa_supplicant, use NetworkManager
|
|
||||||
};
|
|
||||||
|
|
||||||
# Auto-connect to workshop WiFi
|
|
||||||
systemd.services.workshop-wifi = {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "NetworkManager.service" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
User = "workshop";
|
|
||||||
};
|
|
||||||
script = ''
|
|
||||||
sleep 10 # Wait for NetworkManager to start
|
|
||||||
${pkgs.networkmanager}/bin/nmcli dev wifi connect "CODE_CRISPIES_GUEST" password "workshop2024" || true
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Auto-login workshop user
|
|
||||||
services.getty.autologinUser = "workshop";
|
|
||||||
users.users.workshop = {
|
|
||||||
isNormalUser = true;
|
|
||||||
shell = pkgs.zsh;
|
|
||||||
extraGroups = [ "networkmanager" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Workshop shell environment with CORRECT recipes
|
|
||||||
programs.zsh = {
|
|
||||||
enable = true;
|
|
||||||
interactiveShellInit = ''
|
|
||||||
echo "🍪 CODE CRISPIES Workshop Environment"
|
|
||||||
echo "📶 WiFi: CODE_CRISPIES_GUEST"
|
|
||||||
echo "📡 Available servers:"
|
|
||||||
${builtins.concatStringsSep "\n" (map (name:
|
|
||||||
"echo \" - ${name}.codecrispi.es\""
|
|
||||||
) participantNames)}
|
|
||||||
echo ""
|
|
||||||
echo "💡 Commands: connect <name> | recipes | help"
|
|
||||||
|
|
||||||
connect() {
|
|
||||||
[ -z "$1" ] && {
|
|
||||||
echo "Usage: connect <name>"
|
|
||||||
echo "Available: ${builtins.concatStringsSep " " participantNames}"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
echo "🔗 Connecting to $1.codecrispi.es..."
|
|
||||||
ssh -o StrictHostKeyChecking=no workshop@$1.codecrispi.es
|
|
||||||
}
|
|
||||||
|
|
||||||
recipes() {
|
|
||||||
echo "📦 Popular Co-op Cloud recipes (Score 3+):"
|
|
||||||
echo ""
|
|
||||||
echo "🌐 Content Management:"
|
|
||||||
echo " wordpress - CMS/Blog platform"
|
|
||||||
echo " ghost - Headless Node.js CMS"
|
|
||||||
echo " dokuwiki - Simple text-based wiki"
|
|
||||||
echo ""
|
|
||||||
echo "☁️ Productivity & Collaboration:"
|
|
||||||
echo " nextcloud - File sharing & collaboration"
|
|
||||||
echo " hedgedoc - Collaborative markdown editor"
|
|
||||||
echo " collabora - Online office suite"
|
|
||||||
echo " onlyoffice - Office suite with editors"
|
|
||||||
echo " outline - Wiki and knowledge base"
|
|
||||||
echo ""
|
|
||||||
echo "🍽️ Lifestyle & Organization:"
|
|
||||||
echo " mealie - Recipe manager & meal planner"
|
|
||||||
echo ""
|
|
||||||
echo "💬 Communication:"
|
|
||||||
echo " mattermost - Team chat platform"
|
|
||||||
echo " rocketchat - Team communications"
|
|
||||||
echo ""
|
|
||||||
echo "🎯 Event & Community Management:"
|
|
||||||
echo " engelsystem - Volunteer shift management"
|
|
||||||
echo " loomio - Group decision making"
|
|
||||||
echo " mrbs - Meeting room booking"
|
|
||||||
echo " rallly - Doodle poll alternative"
|
|
||||||
echo ""
|
|
||||||
echo "🛠️ Development & Git:"
|
|
||||||
echo " gitea - Self-hosted Git service"
|
|
||||||
echo " custom-php - Custom PHP applications"
|
|
||||||
echo ""
|
|
||||||
echo "🎨 Creative & Media:"
|
|
||||||
echo " owncast - Live streaming platform"
|
|
||||||
echo ""
|
|
||||||
echo "Deploy example:"
|
|
||||||
echo " abra app new wordpress -S --domain=mysite.<yourname>.codecrispi.es"
|
|
||||||
}
|
|
||||||
|
|
||||||
help() {
|
|
||||||
echo "📚 CODE CRISPIES Workshop Guide"
|
|
||||||
echo ""
|
|
||||||
echo "1️⃣ Connect to your assigned server:"
|
|
||||||
echo " connect <yourname> # e.g., connect hopper"
|
|
||||||
echo ""
|
|
||||||
echo "2️⃣ Check your server status:"
|
|
||||||
echo " abra server ls"
|
|
||||||
echo " abra app ls"
|
|
||||||
echo ""
|
|
||||||
echo "3️⃣ Deploy your first app:"
|
|
||||||
echo " abra app new wordpress -S --domain=mysite.<yourname>.codecrispi.es"
|
|
||||||
echo " abra app deploy mysite.<yourname>.codecrispi.es"
|
|
||||||
echo ""
|
|
||||||
echo "4️⃣ Check deployment status:"
|
|
||||||
echo " abra app ps mysite.<yourname>.codecrispi.es"
|
|
||||||
echo " abra app logs mysite.<yourname>.codecrispi.es"
|
|
||||||
echo ""
|
|
||||||
echo "5️⃣ Access your site:"
|
|
||||||
echo " https://mysite.<yourname>.codecrispi.es"
|
|
||||||
echo ""
|
|
||||||
echo "🆘 Need help? Ask the workshop facilitator!"
|
|
||||||
echo "📦 See all recipes: recipes"
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
openssh
|
|
||||||
curl
|
|
||||||
git
|
|
||||||
networkmanager
|
|
||||||
];
|
|
||||||
|
|
||||||
# Auto-start terminal in graphical environment
|
|
||||||
services.xserver = {
|
|
||||||
enable = true;
|
|
||||||
displayManager = {
|
|
||||||
autoLogin.enable = true;
|
|
||||||
autoLogin.user = "workshop";
|
|
||||||
sessionCommands = ''
|
|
||||||
${pkgs.xterm}/bin/xterm -maximized -e ${pkgs.zsh}/bin/zsh &
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
desktopManager.xfce.enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Enable hardware support for most WiFi cards
|
|
||||||
hardware.enableRedistributableFirmware = true;
|
|
||||||
|
|
||||||
# ISO-specific settings
|
|
||||||
isoImage.makeEfiBootable = true;
|
|
||||||
isoImage.makeUsbBootable = true;
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Dev shell
|
|
||||||
devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
|
|
||||||
buildInputs = with nixpkgs.legacyPackages.${system}; [
|
|
||||||
terraform
|
|
||||||
nixos-rebuild
|
|
||||||
docker
|
|
||||||
openssh
|
|
||||||
jq
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user