OSGeoLive 17 · VCAP Nomadic Classroom
Distro Customization Runbook

CalTekNet · github.com/calteknet/osgeo17-vcap · Rev 1.0 · June 2026

Contents

  1. Phase 0 — Verify Fresh Boot State
  2. Phase 1 — Mount Persistent Storage (/mnt/p4)
  3. Phase 2 — Install Core Tools (Docker, Git, Portainer)
  4. Phase 3 — Clone or Init the VCAP Runbook Repo
  5. Phase 4 — Run VCAP Setup Script (vcap_17_setup.sh)
  6. Phase 5 — Portainer Swarm Stack Definitions
  7. Phase 6 — GitHub Push (Browser Method)
  8. Phase 7 — Reproducing On Any Machine (No Persistent Drive)

Phase 0 — Verify Fresh Boot State

Run these first. They tell you exactly what you have before touching anything.

0.1 — Open a Terminal

In OSGeoLive 17 (Lubuntu): right-click the desktop → Open Terminal, or press Ctrl+Alt+T.

0.2 — Who Are You and What OS

# Confirm user and OS version
whoami
lsb_release -a
Expected: user = user · OS = Ubuntu 24.04.2 LTS (OSGeoLive 17)

0.3 — List All Drives and Partitions

# See every disk and partition — find your nvme or usb
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,LABEL,FSTYPE
Look for: nvme0n1p4 (your persistent ext4), sda or sdb (Ventoy USB), sr0 (optical if any)

0.4 — Check Internet

# Confirm network is up
ping -c 3 github.com

0.5 — Check Docker Status

# Is Docker already running?
docker ps
On a fresh OSGeoLive 17 live boot, Docker is NOT installed by default. Phase 2 installs it.

Phase 1 — Mount Persistent Storage (/mnt/p4)

This applies when booting on the i7 with nvme0n1p4. Skip to Phase 2 on machines without this drive.

1.1 — Create the Mount Point

# Only needed once per boot session
sudo mkdir -p /mnt/p4

1.2 — Mount the Partition

# Replace nvme0n1p4 with whatever lsblk showed your ext4 partition as
sudo mount /dev/nvme0n1p4 /mnt/p4

1.3 — Verify Contents

# Should show vcap/ and any prior work
ls -la /mnt/p4/

1.4 — Set Permissions So Your User Can Write

# Allow the live user to write to p4 without sudo every time
sudo chown -R user:user /mnt/p4
The live user on OSGeoLive 17 is user with no password. sudo works without a password.

Phase 2 — Install Core Tools

ONE TIME PER BOOT These install into RAM. Must re-run on each fresh boot unless using a persistent layer.

2.1 — Update Package List

sudo apt-get update -y

2.2 — Install Git and Curl

sudo apt-get install -y git curl wget

2.3 — Install Docker Engine

# Install Docker from the official convenience script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add live user to docker group (no sudo needed for docker commands)
sudo usermod -aG docker user

# Apply group change in current shell
newgrp docker

2.4 — Verify Docker Is Running

docker run hello-world
You should see: Hello from Docker! — if so, Docker is working.

2.5 — Initialize Docker Swarm (Single Node)

# Single-node swarm — required for Portainer stack deployment
docker swarm init

2.6 — Deploy Portainer

# Create Portainer persistent volume
docker volume create portainer_data

# Deploy Portainer CE as a swarm service
docker stack deploy -c - portainer <<'PORTAINER_STACK'
version: '3.8'
services:
  portainer:
    image: portainer/portainer-ce:latest
    ports:
      - "9000:9000"
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    deploy:
      placement:
        constraints:
          - node.role == manager
volumes:
  portainer_data:
    external: true
PORTAINER_STACK

2.7 — Open Portainer in Browser

# Open in your browser — first boot will ask you to set admin password
http://localhost:9000
Set the admin password within 5 minutes or Portainer times out and you must restart the container.

Phase 3 — Clone or Init the VCAP Runbook Repo

Target Repository: github.com/calteknet/osgeo17-vcap

This repo will hold: setup scripts, Docker Compose stack files, PostGIS seed data, MapProxy config, Portainer stack exports, and this runbook HTML.

3.1 — Configure Git Identity (Required Even Without SSH)

# Git needs a name and email to make commits — use your GitHub info
git config --global user.name "Kenneth Wyrick"
git config --global user.email "your-github-email@example.com"

3.2a — If Repo Already Exists: Clone It

# Clone to /mnt/p4/vcap/osgeo17-vcap (persistent) or ~/vcap (RAM only)
git clone https://github.com/calteknet/osgeo17-vcap.git /mnt/p4/vcap/osgeo17-vcap

3.2b — If Repo Does Not Exist Yet: Init Locally First

# Create the directory structure
mkdir -p /mnt/p4/vcap/osgeo17-vcap/{scripts,stacks,config,docs,data}
cd /mnt/p4/vcap/osgeo17-vcap

# Initialize git
git init
git branch -M main

# Create a README
cat > README.md <<'EOF'
# OSGeoLive 17 VCAP Nomadic Classroom

CalTekNet distro customization runbook and setup scripts.
Boots reproducibly from any machine running OSGeoLive 17.

## Structure
- scripts/   — shell setup scripts
- stacks/    — Docker Compose / Portainer stack definitions
- config/    — MapProxy, GeoServer, PostGIS config files
- docs/      — Runbook HTML and reference docs
- data/      — PostGIS seed SQL dumps

## Quick Start
Boot OSGeoLive 17. Open terminal. Run:
  curl -fsSL https://raw.githubusercontent.com/calteknet/osgeo17-vcap/main/scripts/vcap_17_setup.sh | bash
EOF

git add .
git commit -m "init: VCAP nomadic classroom repo structure"
You will push this to GitHub in Phase 6 using a Personal Access Token via the browser.

Phase 4 — vcap_17_setup.sh Master Script

This single script rebuilds the entire VCAP classroom stack on any fresh OSGeoLive 17 boot. Save it to scripts/vcap_17_setup.sh in your repo.

4.1 — Create the Setup Script

# Make sure you're in the repo
cd /mnt/p4/vcap/osgeo17-vcap

# Write the master setup script
cat > scripts/vcap_17_setup.sh <<'SETUPSCRIPT'
#!/usr/bin/env bash
# =============================================================
# vcap_17_setup.sh
# OSGeoLive 17 · VCAP Nomadic Classroom Bootstrap
# CalTekNet · github.com/calteknet/osgeo17-vcap
# Run as: bash scripts/vcap_17_setup.sh
# =============================================================
set -e

VCAP_DIR="${1:-/mnt/p4/vcap}"
REPO_DIR="$VCAP_DIR/osgeo17-vcap"
LOG="$VCAP_DIR/setup_$(date +%Y%m%d_%H%M%S).log"

echo "=== VCAP 17 Setup Starting ===" | tee "$LOG"
echo "Target dir: $VCAP_DIR" | tee -a "$LOG"

# --- 1. System update ---
echo "[1/7] Updating apt..." | tee -a "$LOG"
sudo apt-get update -y >> "$LOG" 2>&1

# --- 2. Install git, curl, wget ---
echo "[2/7] Installing git curl wget..." | tee -a "$LOG"
sudo apt-get install -y git curl wget >> "$LOG" 2>&1

# --- 3. Install Docker ---
echo "[3/7] Installing Docker..." | tee -a "$LOG"
if ! command -v docker &> /dev/null; then
  curl -fsSL https://get.docker.com -o /tmp/get-docker.sh
  sudo sh /tmp/get-docker.sh >> "$LOG" 2>&1
  sudo usermod -aG docker user
  echo "Docker installed." | tee -a "$LOG"
else
  echo "Docker already present." | tee -a "$LOG"
fi

# --- 4. Start Docker swarm ---
echo "[4/7] Initializing Docker swarm..." | tee -a "$LOG"
if ! docker info 2>/dev/null | grep -q "Swarm: active"; then
  newgrp docker <> "$LOG" 2>&1
INNEREOF
  echo "Swarm initialized." | tee -a "$LOG"
else
  echo "Swarm already active." | tee -a "$LOG"
fi

# --- 5. Deploy Portainer ---
echo "[5/7] Deploying Portainer..." | tee -a "$LOG"
docker volume create portainer_data >> "$LOG" 2>&1 || true
docker stack deploy -c "$REPO_DIR/stacks/portainer.yml" portainer >> "$LOG" 2>&1
echo "Portainer → http://localhost:9000" | tee -a "$LOG"

# --- 6. Deploy VCAP classroom stack ---
echo "[6/7] Deploying VCAP classroom stack..." | tee -a "$LOG"
docker stack deploy -c "$REPO_DIR/stacks/vcap-classroom.yml" vcap >> "$LOG" 2>&1
echo "VCAP stack deployed." | tee -a "$LOG"

# --- 7. Done ---
echo "" | tee -a "$LOG"
echo "=== Setup Complete ===" | tee -a "$LOG"
echo "Portainer:   http://localhost:9000" | tee -a "$LOG"
echo "GeoServer:   http://localhost:8080/geoserver" | tee -a "$LOG"
echo "MapProxy:    http://localhost:8070" | tee -a "$LOG"
echo "Jupyter:     http://localhost:8888" | tee -a "$LOG"
echo "Log saved:   $LOG" | tee -a "$LOG"
SETUPSCRIPT

# Make it executable
chmod +x scripts/vcap_17_setup.sh

4.2 — Commit the Script

cd /mnt/p4/vcap/osgeo17-vcap
git add scripts/vcap_17_setup.sh
git commit -m "feat: add vcap_17_setup.sh master bootstrap script"

Phase 5 — Portainer Stack Definitions

Two YAML files. These define all services. Portainer reads them. Save both to stacks/.

5.1 — Portainer Stack File

cat > /mnt/p4/vcap/osgeo17-vcap/stacks/portainer.yml <<'EOF'
version: '3.8'
services:
  portainer:
    image: portainer/portainer-ce:latest
    ports:
      - "9000:9000"
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    deploy:
      placement:
        constraints:
          - node.role == manager
volumes:
  portainer_data:
    external: true
EOF

5.2 — VCAP Classroom Stack File

cat > /mnt/p4/vcap/osgeo17-vcap/stacks/vcap-classroom.yml <<'EOF'
version: '3.8'

# VCAP Nomadic Classroom Stack
# CalTekNet · OSGeoLive 17
# Services: PostGIS · GeoServer · MapProxy · Jupyter · GeoNetwork

networks:
  vcap_net:
    driver: overlay
    attachable: true

volumes:
  postgis_data:
  geoserver_data:
  mapproxy_cache:
  jupyter_work:

services:

  postgis:
    image: postgis/postgis:17-3.5
    environment:
      POSTGRES_USER: vcap
      POSTGRES_PASSWORD: vcap2026
      POSTGRES_DB: vcap_classroom
    volumes:
      - postgis_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - vcap_net
    deploy:
      replicas: 1

  geoserver:
    image: kartoza/geoserver:2.27.1
    environment:
      GEOSERVER_ADMIN_USER: admin
      GEOSERVER_ADMIN_PASSWORD: geoserver
      GEOWEBCACHE_CACHE_DIR: /opt/geoserver/data_dir/gwc
    volumes:
      - geoserver_data:/opt/geoserver/data_dir
    ports:
      - "8080:8080"
    networks:
      - vcap_net
    depends_on:
      - postgis
    deploy:
      replicas: 1

  mapproxy:
    image: kartoza/mapproxy:latest
    volumes:
      - mapproxy_cache:/mapproxy/cache_data
    ports:
      - "8070:8080"
    networks:
      - vcap_net
    deploy:
      replicas: 1

  jupyter:
    image: jupyter/scipy-notebook:latest
    environment:
      JUPYTER_ENABLE_LAB: "yes"
      JUPYTER_TOKEN: "vcap2026"
    volumes:
      - jupyter_work:/home/jovyan/work
    ports:
      - "8888:8888"
    networks:
      - vcap_net
    deploy:
      replicas: 1

EOF

5.3 — Commit Stack Files

cd /mnt/p4/vcap/osgeo17-vcap
git add stacks/
git commit -m "feat: add portainer and vcap-classroom stack definitions"

Phase 6 — Push to GitHub (Browser Token Method)

No SSH key configured. Use a Personal Access Token (PAT) via HTTPS. One-time setup per machine per session.

6.1 — Create a GitHub Personal Access Token

  1. Open browser → github.com → log in as calteknet
  2. Click your avatar (top right) → Settings
  3. Left sidebar → Developer settingsPersonal access tokensTokens (classic)
  4. Click Generate new token (classic)
  5. Note: osgeo17-vcap live session
  6. Expiration: 7 days (or 30 days)
  7. Scopes: check repo (top-level — covers all repo permissions)
  8. Click Generate tokencopy it immediately, it won't show again
The token is shown ONCE. Copy it before closing the page.

6.2 — Create the Repo on GitHub (If New)

  1. github.com → + (top right) → New repository
  2. Owner: calteknet
  3. Name: osgeo17-vcap
  4. Description: OSGeoLive 17 VCAP Nomadic Classroom distro customization
  5. Visibility: Public
  6. Do NOT initialize with README (you already have one)
  7. Click Create repository

6.3 — Add Remote and Push from Terminal

cd /mnt/p4/vcap/osgeo17-vcap

# Add GitHub as remote — use your actual token where TOKEN appears
git remote add origin https://TOKEN@github.com/calteknet/osgeo17-vcap.git

# Push everything
git push -u origin main
Replace TOKEN with the actual token string you copied. Example: https://ghp_abc123xyz@github.com/...

6.4 — Verify in Browser

Open github.com/calteknet/osgeo17-vcap — you should see your files: README.md, scripts/, stacks/, docs/, data/.

6.5 — Save This Runbook to docs/

# Copy this runbook HTML into the repo docs folder
cp /path/to/osgeo17-vcap-runbook.html /mnt/p4/vcap/osgeo17-vcap/docs/

cd /mnt/p4/vcap/osgeo17-vcap
git add docs/
git commit -m "docs: add distro customization runbook HTML"
git push

Phase 7 — Reproducing on Any Machine (No Persistent Drive)

Once the repo is on GitHub, any machine booted on OSGeoLive 17 can run the full stack in three commands.

7.1 — The Three-Command Bootstrap (Any Machine)

# Step 1: Install git (may already be present)
sudo apt-get install -y git

# Step 2: Clone the runbook repo to RAM (no persistent drive needed)
git clone https://github.com/calteknet/osgeo17-vcap.git ~/vcap

# Step 3: Run the setup script
bash ~/vcap/scripts/vcap_17_setup.sh ~/vcap
This installs Docker, initializes swarm, deploys Portainer + VCAP classroom stack. Takes ~5–10 minutes on first run depending on internet speed.

7.2 — Service URLs After Bootstrap

http://localhost:9000   # Portainer (set admin password on first boot)
http://localhost:8080/geoserver   # GeoServer (admin / geoserver)
http://localhost:8070   # MapProxy tile cache
http://localhost:8888   # Jupyter Lab (token: vcap2026)
localhost:5432          # PostGIS (vcap / vcap2026 / vcap_classroom)

7.3 — Saving Work From a RAM-Only Session

# Export PostGIS databases before shutting down
docker exec $(docker ps -q -f name=postgis) \
  pg_dumpall -U vcap > ~/vcap/data/postgis_dump_$(date +%Y%m%d).sql

# Commit and push the dump to GitHub
cd ~/vcap
git add data/
git commit -m "data: postgis dump $(date +%Y%m%d)"
git push
On a live boot with no persistent drive, ALL work is lost on shutdown unless pushed to GitHub or copied to a USB drive.