From 45fd35a5e9b516d7d83b5e4b6a51e09a6a0a192f Mon Sep 17 00:00:00 2001 From: dev Date: Tue, 20 Oct 2026 10:52:22 +0000 Subject: [PATCH] Delete docs/webvm-selfhost.md --- docs/webvm-selfhost.md | 373 ----------------------------------------- 1 file changed, 373 deletions(-) delete mode 100644 docs/webvm-selfhost.md diff --git a/docs/webvm-selfhost.md b/docs/webvm-selfhost.md deleted file mode 100644 index afee5e4..0000000 --- a/docs/webvm-selfhost.md +++ /dev/null @@ -1,373 +0,0 @@ -webvm for self host - ---- - -install script: - -- install required packages -- create `/opt/webvm-aio` -- ask for: - - domain - - Let's Encrypt email - - image filename -- write: - - `.env` - - `docker-compose.caddy.yml` - - `docker-compose.webvm.yml` - - `Caddyfile` - - `nginx.conf` - - `bootstrap.sh` - - `deploy.sh` -- create the shared Docker network `web` -- start Caddy -- tell you where to upload your `.ext2` image -- optionally bootstrap immediately if the image is already present - ---- - -### copy-paste - -[debian .ext2](https://github.com/leaningtech/webvm/releases/download/ext2_image/debian_mini_20230519_5022088024.ext2) - -[alpine .ext2](https://github.com/leaningtech/alpine-image/tree/master) - -run as sudo-capable user: - -```bash -bash <(cat <<'EOF' -set -euo pipefail - -ROOT_DIR="/opt/webvm-aio" - -echo "==> WebVM AIO installer" - -if ! command -v sudo >/dev/null 2>&1; then - echo "sudo is required" - exit 1 -fi - -read -rp "Domain (e.g. webvm.example.com): " WEBVM_DOMAIN -read -rp "Let's Encrypt email: " LETSENCRYPT_EMAIL -read -rp "Disk image filename (e.g. debian_mini_20230519_5022088024.ext2): " WEBVM_IMAGE - -if [ -z "${WEBVM_DOMAIN}" ] || [ -z "${LETSENCRYPT_EMAIL}" ] || [ -z "${WEBVM_IMAGE}" ]; then - echo "All fields are required." - exit 1 -fi - -echo "==> Installing packages" -sudo apt update -sudo apt install -y git curl docker.io docker-compose-plugin nodejs npm python3 - -echo "==> Enabling docker" -sudo systemctl enable --now docker - -echo "==> Creating layout at $ROOT_DIR" -sudo mkdir -p "$ROOT_DIR" -sudo chown -R "$USER":"$USER" "$ROOT_DIR" - -mkdir -p "$ROOT_DIR"/{images,index,src} -mkdir -p "$ROOT_DIR/index/custom-disk-images" - -cat > "$ROOT_DIR/.env" < "$ROOT_DIR/docker-compose.caddy.yml" <<'YAML' -version: "3.9" - -services: - caddy: - image: lucaslorentz/caddy-docker-proxy:2.9-alpine - container_name: caddy - restart: unless-stopped - ports: - - "80:80" - - "443:443" - environment: - - CADDY_INGRESS_NETWORKS=web - networks: - - web - volumes: - - /var/run/docker.sock:/var/run/docker.sock:ro - - ./Caddyfile:/etc/caddy/Caddyfile:ro - - caddy_data:/data - - caddy_config:/config - -networks: - web: - external: true - -volumes: - caddy_data: - caddy_config: -YAML - -cat > "$ROOT_DIR/docker-compose.webvm.yml" <<'YAML' -version: "3.9" - -services: - webvm: - image: nginx:alpine - container_name: webvm - restart: unless-stopped - networks: - - web - volumes: - - ./index:/usr/share/nginx/html:ro - - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro - labels: - caddy: ${WEBVM_DOMAIN} - caddy.reverse_proxy: "{{upstreams 80}}" - caddy.encode: zstd gzip - -networks: - web: - external: true -YAML - -cat > "$ROOT_DIR/Caddyfile" <<'CADDY' -{ - email {$LETSENCRYPT_EMAIL} -} -CADDY - -cat > "$ROOT_DIR/nginx.conf" <<'NGINX' -server { - listen 80; - server_name _; - - root /usr/share/nginx/html; - index index.html; - - types { - application/wasm wasm; - } - - add_header Cross-Origin-Opener-Policy same-origin always; - add_header Cross-Origin-Embedder-Policy require-corp always; - add_header Cross-Origin-Resource-Policy same-origin always; - add_header X-Content-Type-Options nosniff always; - - location / { - try_files $uri $uri/ /index.html; - } - - location /custom-disk-images/ { - autoindex off; - add_header Cache-Control "public, max-age=3600"; - try_files $uri =404; - } - - location ~* \.(wasm|bin|img|ext2)$ { - add_header Cache-Control "public, max-age=3600"; - try_files $uri =404; - } - - location ~* \.(js|mjs|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf)$ { - add_header Cache-Control "public, max-age=31536000, immutable"; - try_files $uri =404; - } - - client_max_body_size 50m; -} -NGINX - -cat > "$ROOT_DIR/bootstrap.sh" <<'BOOT' -#!/usr/bin/env bash -set -euo pipefail - -ROOT_DIR="${WEBVM_ROOT:-/opt/webvm-aio}" -if [ -f "$ROOT_DIR/.env" ]; then - set -a - . "$ROOT_DIR/.env" - set +a -fi - -SRC_DIR="$ROOT_DIR/src/webvm" -PUB_DIR="$ROOT_DIR/index" -IMG_SRC_DIR="$ROOT_DIR/images" -IMG_NAME="${WEBVM_IMAGE:-debian_mini_20230519_5022088024.ext2}" -IMG_SRC="$IMG_SRC_DIR/$IMG_NAME" -IMG_PUB_DIR="$PUB_DIR/custom-disk-images" -IMG_PUB="$IMG_PUB_DIR/$IMG_NAME" - -echo "==> root: $ROOT_DIR" -echo "==> source: $SRC_DIR" -echo "==> publish: $PUB_DIR" -echo "==> image source: $IMG_SRC" - -mkdir -p "$ROOT_DIR" "$ROOT_DIR/src" "$PUB_DIR" "$IMG_SRC_DIR" "$IMG_PUB_DIR" - -if ! command -v docker >/dev/null 2>&1; then - echo "ERROR: docker is not installed" - exit 1 -fi - -if ! docker network inspect web >/dev/null 2>&1; then - echo "==> creating shared docker network: web" - docker network create web -fi - -echo "==> starting caddy" -cd "$ROOT_DIR" -docker compose --env-file .env -f docker-compose.caddy.yml up -d - -if [ ! -f "$IMG_SRC" ]; then - echo - echo "ERROR: missing disk image:" - echo " $IMG_SRC" - echo - echo "Upload your .ext2 image there, then rerun:" - echo " $ROOT_DIR/bootstrap.sh" - echo - exit 1 -fi - -if [ ! -d "$SRC_DIR/.git" ]; then - echo "==> cloning webvm" - git clone https://github.com/leaningtech/webvm.git "$SRC_DIR" -else - echo "==> updating webvm" - git -C "$SRC_DIR" pull --ff-only -fi - -cd "$SRC_DIR" - -echo "==> installing dependencies" -npm install - -CONFIG_FILE="$SRC_DIR/config_public_terminal.js" - -echo "==> patching WebVM config" -python3 - < building webvm" -npm install -npm run build - -echo "==> publishing build" -rm -rf "$PUB_DIR"/* -mkdir -p "$IMG_PUB_DIR" - -if [ -d "$SRC_DIR/dist" ]; then - cp -r "$SRC_DIR/dist/"* "$PUB_DIR"/ -else - echo "ERROR: expected build output in $SRC_DIR/dist" - exit 1 -fi - -cp "$IMG_SRC" "$IMG_PUB" - -echo "==> starting webvm" -cd "$ROOT_DIR" -docker compose --env-file .env -f docker-compose.webvm.yml up -d - -echo -echo "Done." -echo "Site: https://${WEBVM_DOMAIN}" -echo "Image: https://${WEBVM_DOMAIN}/custom-disk-images/$IMG_NAME" -BOOT - -cat > "$ROOT_DIR/deploy.sh" <<'DEPLOY' -#!/usr/bin/env bash -set -euo pipefail -ROOT_DIR="/opt/webvm-aio" -cd "$ROOT_DIR" -./bootstrap.sh -docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" -DEPLOY - -chmod +x "$ROOT_DIR/bootstrap.sh" "$ROOT_DIR/deploy.sh" - -echo "==> Ensuring docker network exists" -docker network inspect web >/dev/null 2>&1 || docker network create web - -echo "==> Starting Caddy" -cd "$ROOT_DIR" -docker compose --env-file .env -f docker-compose.caddy.yml up -d - -echo -echo "==> Install complete" -echo -echo "Next steps:" -echo "1. Point DNS for $WEBVM_DOMAIN to this server." -echo "2. Upload your disk image to:" -echo " $ROOT_DIR/images/$WEBVM_IMAGE" -echo -echo "Example upload:" -echo " scp $WEBVM_IMAGE $USER@$(hostname -I | awk '{print $1}'):$ROOT_DIR/images/" -echo -read -rp "If the image is already present, bootstrap now? [y/N]: " DO_BOOTSTRAP -if [[ "${DO_BOOTSTRAP:-}" =~ ^[Yy]$ ]]; then - "$ROOT_DIR/bootstrap.sh" -else - echo - echo "When ready, run:" - echo " cd $ROOT_DIR && ./bootstrap.sh" -fi -EOF -) -``` - ---- - -## After running it - -### 1. Point DNS -Set `A` record for your domain to your VPS IP. - -### 2. Upload the `.ext2` image -Example: - -```bash -scp debian_mini_20230519_5022088024.ext2 user@your-server:/opt/webvm-aio/images/ -``` - -### 3. Bootstrap -```bash -cd /opt/webvm-aio -./bootstrap.sh -``` - -### 4. Open -```text -https://your-domain -``` - ---- - -## Notes - -### If ports 80/443 are already used -Stop any existing web server before running Caddy: - -```bash -sudo systemctl stop nginx -sudo systemctl disable nginx -``` - -or stop any existing container using 80/443.