Restore AppFactory scripts to stable versions

This commit is contained in:
2026-05-27 09:29:18 +02:00
parent b6ed79cc3f
commit 438c29e2e0
9 changed files with 88 additions and 254 deletions
+19 -13
View File
@@ -1,22 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/opt/appfactory"
BACKUP_DIR="$BASE_DIR/backups"
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
source "$CONFIG_FILE"
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP_FILE="$BACKUP_DIR/appfactory-backup-$TIMESTAMP.tar.gz"
mkdir -p "$BACKUP_DIR"
tar -czf "$BACKUP_FILE" \
/opt/appfactory/apps \
/opt/appfactory/config \
/opt/appfactory/data/gitea \
/opt/appfactory/data/registry \
/opt/appfactory/deploy \
/opt/appfactory/gateway \
/opt/appfactory/templates \
/opt/appfactory/services \
/home/jiri/workspace
echo "Creating backup:"
echo "$BACKUP_FILE"
tar -czf "$BACKUP_FILE" \
"$APPFACTORY_DIR/apps" \
"$APPFACTORY_DIR/config" \
"$APPFACTORY_DIR/data/gitea" \
"$APPFACTORY_DIR/data/registry" \
"$APPFACTORY_DIR/deploy" \
"$APPFACTORY_DIR/gateway" \
"$APPFACTORY_DIR/templates" \
"$APPFACTORY_DIR/services" \
"$WORKSPACE_DIR"
echo ""
echo "DONE"
echo "$BACKUP_FILE"
+4 -49
View File
@@ -10,7 +10,6 @@ WORKSPACE_DIR="/home/$APP_USER/workspace"
echo "======================================================"
echo "AppFactory Bootstrap"
echo "======================================================"
echo ""
echo "User: $APP_USER"
echo "Workspace: $WORKSPACE_DIR"
echo "AppFactory: $APPFACTORY_DIR"
@@ -23,74 +22,30 @@ if [ "$CONFIRM" != "yes" ]; then
exit 1
fi
echo ""
echo "Updating system..."
apt update
apt install -y \
docker.io \
docker-compose-plugin \
git \
curl \
jq \
python3 \
python3-pip
echo ""
echo "Enabling Docker..."
apt install -y docker.io docker-compose-plugin git curl jq python3 python3-pip
systemctl enable docker
systemctl start docker
echo ""
echo "Adding user to docker group..."
usermod -aG docker "$APP_USER"
echo ""
echo "Creating directories..."
mkdir -p "$APPFACTORY_DIR"
mkdir -p "$APPFACTORY_DIR/apps"
mkdir -p "$APPFACTORY_DIR/backups"
mkdir -p "$APPFACTORY_DIR/config"
mkdir -p "$APPFACTORY_DIR/data"
mkdir -p "$APPFACTORY_DIR/data/gitea"
mkdir -p "$APPFACTORY_DIR/data/registry"
mkdir -p "$APPFACTORY_DIR/deploy"
mkdir -p "$APPFACTORY_DIR/gateway"
mkdir -p "$APPFACTORY_DIR/gateway/static"
mkdir -p "$APPFACTORY_DIR/services"
mkdir -p "$APPFACTORY_DIR/templates"
mkdir -p "$APPFACTORY_DIR"/{apps,backups,config,data/gitea,data/registry,deploy,gateway/static,services,templates}
mkdir -p "$WORKSPACE_DIR"
echo ""
echo "Creating config..."
cat > "$APPFACTORY_DIR/config/appfactory.env" <<EOF
cat > "$APPFACTORY_DIR/config/appfactory.env" <<EOF_ENV
APP_USER="$APP_USER"
APP_GROUP="$APP_GROUP"
APPFACTORY_DIR="$APPFACTORY_DIR"
WORKSPACE_DIR="$WORKSPACE_DIR"
BACKUP_DIR="$APPFACTORY_DIR/backups"
EOF
EOF_ENV
chmod 600 "$APPFACTORY_DIR/config/appfactory.env"
echo ""
echo "Fixing ownership..."
chown -R "$APP_USER:$APP_GROUP" "$APPFACTORY_DIR"
chown -R "$APP_USER:$APP_GROUP" "$WORKSPACE_DIR"
echo ""
echo "Bootstrap complete."
echo ""
echo "IMPORTANT:"
echo "Logout/login again so docker group is applied."
echo ""
echo "Next steps:"
echo "1. clone appfactory-tools"
echo "2. restore backup"
echo ""
+15 -50
View File
@@ -4,35 +4,24 @@ set -euo pipefail
APP_ID="${1:-}"
if [ -z "$APP_ID" ]; then
echo "Usage:"
echo " ./delete-app.sh <app-id>"
echo "Usage: ./delete-app.sh <app-id>"
exit 1
fi
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
fi
APPFACTORY_DIR="${APPFACTORY_DIR:-/opt/appfactory}"
WORKSPACE_DIR="${WORKSPACE_DIR:-/home/jiri/workspace}"
source "$CONFIG_FILE"
COMPOSE_FILE="$APPFACTORY_DIR/deploy/apps-compose.yml"
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
CADDY_FILE="$APPFACTORY_DIR/gateway/Caddyfile"
TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools"
echo "Deleting app: $APP_ID"
if [ -n "${GITEA_URL:-}" ] && [ -n "${GITEA_TOKEN:-}" ] && [ -n "${GITEA_ORG:-}" ]; then
echo "Deleting Gitea repository..."
curl -sS -X DELETE \
"$GITEA_URL/api/v1/repos/$GITEA_ORG/$APP_ID" \
-H "Authorization: token $GITEA_TOKEN" || true
fi
echo "Deleting Gitea repository..."
curl -sS -X DELETE \
"$GITEA_URL/api/v1/repos/$GITEA_ORG/$APP_ID" \
-H "Authorization: token $GITEA_TOKEN" || true
echo "Stopping container..."
docker rm -f "$APP_ID" || true
@@ -55,61 +44,37 @@ caddy_file = Path(sys.argv[4])
def remove_block(lines, predicate):
out = []
i = 0
while i < len(lines):
line = lines[i]
if predicate(line):
indent = len(line) - len(line.lstrip())
i += 1
while i < len(lines):
next_line = lines[i]
if next_line.strip():
next_indent = len(next_line) - len(next_line.lstrip())
if next_indent <= indent:
break
i += 1
continue
out.append(line)
i += 1
return out
if compose_file.exists():
compose_lines = compose_file.read_text().splitlines()
compose_lines = remove_block(
compose_lines,
lambda l: l.startswith(f" {app_id}:")
)
compose_file.write_text("\n".join(compose_lines) + "\n")
lines = compose_file.read_text().splitlines()
lines = remove_block(lines, lambda l: l.startswith(f" {app_id}:"))
compose_file.write_text("\n".join(lines).rstrip() + "\n")
if catalog_file.exists():
catalog_lines = catalog_file.read_text().splitlines()
catalog_lines = remove_block(
catalog_lines,
lambda l: l.strip() == f"- id: {app_id}"
)
catalog_file.write_text("\n".join(catalog_lines) + "\n")
lines = catalog_file.read_text().splitlines()
lines = remove_block(lines, lambda l: l.strip() == f"- id: {app_id}")
catalog_file.write_text("\n".join(lines).rstrip() + "\n")
if caddy_file.exists():
caddy_lines = caddy_file.read_text().splitlines()
caddy_lines = remove_block(
caddy_lines,
lambda l: f"/apps/{app_id}/*" in l
)
caddy_file.write_text("\n".join(caddy_lines) + "\n")
lines = caddy_file.read_text().splitlines()
lines = remove_block(lines, lambda l: f"/apps/{app_id}/*" in l)
caddy_file.write_text("\n".join(lines).rstrip() + "\n")
PY
echo "Regenerating generated files..."
+7 -13
View File
@@ -4,19 +4,12 @@ set -euo pipefail
APP_ID="${1:-}"
if [ -z "$APP_ID" ]; then
echo "Usage:"
echo " ./deploy-app.sh <app-id>"
echo "Usage: ./deploy-app.sh <app-id>"
exit 1
fi
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
fi
APPFACTORY_DIR="${APPFACTORY_DIR:-/opt/appfactory}"
WORKSPACE_DIR="${WORKSPACE_DIR:-/home/jiri/workspace}"
source "$CONFIG_FILE"
APP_SOURCE_DIR="$WORKSPACE_DIR/$APP_ID"
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
@@ -32,14 +25,15 @@ if [ ! -f "$APP_SOURCE_DIR/Dockerfile" ]; then
exit 1
fi
chown -R "$APP_USER:$APP_GROUP" "$APP_SOURCE_DIR" || true
echo "Updating source code..."
cd "$APP_SOURCE_DIR"
if [ -d ".git" ]; then
git config --global --add safe.directory "$APP_SOURCE_DIR" || true
git fetch origin main
git reset --hard origin/main
else
echo "WARNING: $APP_SOURCE_DIR is not a git repository"
fi
echo "Building Docker image..."
@@ -63,7 +57,7 @@ cat >> "$CATALOG_FILE" <<EOF_APP
EOF_APP
fi
echo "Regenerating compose, Caddyfile and apps page..."
echo "Regenerating generated files..."
"$TOOLS_DIR/scripts/generate-apps-compose.sh"
"$TOOLS_DIR/scripts/generate-caddyfile.sh"
@@ -77,4 +71,4 @@ docker compose -f docker-compose.yml -f apps-compose.yml up -d --force-recreate
echo ""
echo "DONE"
echo "Open:"
echo "${APPFACTORY_PUBLIC_URL:-http://192.168.66.130}/apps/$APP_ID/docs"
echo "$APPFACTORY_PUBLIC_URL/apps/$APP_ID/docs"
+5 -4
View File
@@ -1,9 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/opt/appfactory"
CATALOG_FILE="$BASE_DIR/apps/catalog.yml"
COMPOSE_FILE="$BASE_DIR/deploy/apps-compose.yml"
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
source "$CONFIG_FILE"
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
COMPOSE_FILE="$APPFACTORY_DIR/deploy/apps-compose.yml"
cat > "$COMPOSE_FILE" <<'EOF_COMPOSE'
services:
@@ -11,7 +13,6 @@ EOF_COMPOSE
awk '
/- id:/ { app=$3 }
/language:/ { lang=$2 }
/status:/ {
if (app != "") {
print " " app ":"
+9 -7
View File
@@ -1,14 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/opt/appfactory"
CATALOG_FILE="$BASE_DIR/apps/catalog.yml"
OUTPUT_DIR="$BASE_DIR/gateway/static"
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
source "$CONFIG_FILE"
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
OUTPUT_DIR="$APPFACTORY_DIR/gateway/static"
OUTPUT_FILE="$OUTPUT_DIR/apps.html"
mkdir -p "$OUTPUT_DIR"
cat > "$OUTPUT_FILE" <<'EOF'
cat > "$OUTPUT_FILE" <<'EOF_HTML'
<!doctype html>
<html>
<head>
@@ -31,7 +33,7 @@ cat > "$OUTPUT_FILE" <<'EOF'
<th>Docs</th>
<th>Health</th>
</tr>
EOF
EOF_HTML
awk '
function print_row() {
@@ -57,10 +59,10 @@ awk '
}
' "$CATALOG_FILE" >> "$OUTPUT_FILE"
cat >> "$OUTPUT_FILE" <<'EOF'
cat >> "$OUTPUT_FILE" <<'EOF_HTML'
</table>
</body>
</html>
EOF
EOF_HTML
echo "Generated: $OUTPUT_FILE"
+6 -4
View File
@@ -1,9 +1,11 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="/opt/appfactory"
CATALOG_FILE="$BASE_DIR/apps/catalog.yml"
CADDY_FILE="$BASE_DIR/gateway/Caddyfile"
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
source "$CONFIG_FILE"
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
CADDY_FILE="$APPFACTORY_DIR/gateway/Caddyfile"
cat > "$CADDY_FILE" <<'EOF_CADDY'
:80 {
@@ -48,4 +50,4 @@ cat >> "$CADDY_FILE" <<'EOF_CADDY'
}
EOF_CADDY
docker exec appfactory-caddy caddy reload --config /etc/caddy/Caddyfile
docker exec appfactory-caddy caddy reload --config /etc/caddy/Caddyfile || docker restart appfactory-caddy
+5 -26
View File
@@ -1,24 +1,14 @@
#!/usr/bin/env bash
set -euo pipefail
CONFIG_FILE="$HOME/.appfactory/env"
if [ ! -f "$CONFIG_FILE" ]; then
echo "Missing config file: $CONFIG_FILE"
exit 1
fi
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
source "$CONFIG_FILE"
APP_ID="${1:-}"
APP_NAME="${2:-$APP_ID}"
if [ -z "$APP_ID" ]; then
echo "Usage:"
echo " ./new-python-app.sh <app-id> [app-name]"
echo ""
echo "Example:"
echo " ./new-python-app.sh gmail-app \"Gmail App\""
echo "Usage: ./new-python-app.sh <app-id> [app-name]"
exit 1
fi
@@ -48,7 +38,7 @@ id: $APP_ID
name: $APP_NAME
language: python
version: 1.0.0
base_path: /$APP_ID
base_path: /apps/$APP_ID
port: 8000
status: development
EOF_APP
@@ -57,19 +47,6 @@ cat > README.md <<EOF_README
# $APP_NAME
Generated by AppFactory.
## Local build
\`\`\`bash
docker build -t $APP_ID .
docker run --rm -p 8001:8000 $APP_ID
\`\`\`
Open:
\`\`\`text
http://SERVER_IP:8001/docs
\`\`\`
EOF_README
echo "Creating Gitea repository..."
@@ -122,6 +99,8 @@ git add .
git commit -m "Initial $APP_NAME"
git push -u origin main
chown -R "$APP_USER:$APP_GROUP" "$TARGET_DIR" || true
echo ""
echo "DONE"
echo "Repository:"
+18 -88
View File
@@ -23,15 +23,6 @@ fi
if [ "$FORCE" != "true" ]; then
echo "REFUSING TO RUN RESTORE."
echo ""
echo "Restore overwrites:"
echo "- $APPFACTORY_DIR"
echo "- $WORKSPACE_DIR"
echo "- Gitea data"
echo "- Registry data"
echo "- deployed apps"
echo "- catalog"
echo "- gateway config"
echo ""
echo "Usage:"
echo " sudo ./restore-appfactory.sh --force /path/to/backup.tar.gz"
exit 1
@@ -39,14 +30,11 @@ fi
if [ -z "$BACKUP_FILE" ]; then
echo "Missing backup file."
echo "Usage:"
echo " sudo ./restore-appfactory.sh --force /path/to/backup.tar.gz"
exit 1
fi
if [ ! -f "$BACKUP_FILE" ]; then
echo "Backup file not found:"
echo "$BACKUP_FILE"
echo "Backup file not found: $BACKUP_FILE"
exit 1
fi
@@ -61,8 +49,6 @@ echo "This will overwrite:"
echo " $APPFACTORY_DIR"
echo " $WORKSPACE_DIR"
echo ""
echo "Before restore, an emergency backup will be created."
echo ""
read -r -p "Type RESTORE to continue: " CONFIRM
@@ -72,29 +58,17 @@ if [ "$CONFIRM" != "RESTORE" ]; then
fi
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
EMERGENCY_BACKUP_DIR="${BACKUP_DIR:-/opt/appfactory/backups}"
EMERGENCY_BACKUP_FILE="$EMERGENCY_BACKUP_DIR/emergency-before-restore-$TIMESTAMP.tar.gz"
EMERGENCY_BACKUP_FILE="$BACKUP_DIR/emergency-before-restore-$TIMESTAMP.tar.gz"
mkdir -p "$EMERGENCY_BACKUP_DIR"
mkdir -p "$BACKUP_DIR"
echo ""
echo "Creating emergency backup:"
echo "$EMERGENCY_BACKUP_FILE"
tar -czf "$EMERGENCY_BACKUP_FILE" \
"$APPFACTORY_DIR" \
"$WORKSPACE_DIR" \
2>/tmp/appfactory-emergency-backup-errors.log || {
echo "Emergency backup failed."
echo "Errors:"
cat /tmp/appfactory-emergency-backup-errors.log
exit 1
}
"$WORKSPACE_DIR"
echo ""
echo "Emergency backup created."
echo ""
echo "Stopping AppFactory containers..."
if [ -d "$APPFACTORY_DIR/deploy" ]; then
@@ -102,85 +76,41 @@ if [ -d "$APPFACTORY_DIR/deploy" ]; then
docker compose -f docker-compose.yml -f apps-compose.yml down || true
fi
echo ""
echo "Restoring files from backup..."
echo "Restoring backup..."
tar -xzf "$BACKUP_FILE" -C /
echo ""
echo "Fixing ownership..."
chown -R "$APP_USER:$APP_GROUP" "$APPFACTORY_DIR"
chown -R "$APP_USER:$APP_GROUP" "$WORKSPACE_DIR"
chmod 600 "$APPFACTORY_DIR/config/appfactory.env" || true
if [ -f "$APPFACTORY_DIR/config/appfactory.env" ]; then
chmod 600 "$APPFACTORY_DIR/config/appfactory.env"
fi
echo ""
echo "Starting core services..."
cd "$APPFACTORY_DIR/deploy"
docker compose -f docker-compose.yml up -d
echo ""
echo "Regenerating generated files..."
TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools"
if [ ! -d "$TOOLS_DIR" ]; then
echo "Missing tools directory:"
echo "$TOOLS_DIR"
echo ""
echo "Core services started, but app rebuild skipped."
exit 0
fi
if [ -d "$TOOLS_DIR" ]; then
cd "$TOOLS_DIR"
cd "$TOOLS_DIR"
./scripts/generate-apps-compose.sh || true
./scripts/generate-caddyfile.sh || true
./scripts/generate-apps-page.sh || true
if [ -x "./scripts/generate-apps-compose.sh" ]; then
./scripts/generate-apps-compose.sh
fi
if [ -x "./scripts/generate-caddyfile.sh" ]; then
./scripts/generate-caddyfile.sh
fi
if [ -x "./scripts/generate-apps-page.sh" ]; then
./scripts/generate-apps-page.sh
fi
echo ""
echo "Rebuilding apps from workspace..."
for app_dir in "$WORKSPACE_DIR"/*; do
if [ -f "$app_dir/app.yml" ]; then
app_id="$(basename "$app_dir")"
echo ""
echo "Rebuilding app: $app_id"
if [ -x "$TOOLS_DIR/scripts/deploy-app.sh" ]; then
"$TOOLS_DIR/scripts/deploy-app.sh" "$app_id" || {
echo "WARNING: failed to rebuild app: $app_id"
}
for app_dir in "$WORKSPACE_DIR"/*; do
if [ -f "$app_dir/app.yml" ]; then
app_id="$(basename "$app_dir")"
echo "Rebuilding app: $app_id"
./scripts/deploy-app.sh "$app_id" || true
fi
fi
done
done
fi
echo ""
echo "Final compose up..."
cd "$APPFACTORY_DIR/deploy"
docker compose -f docker-compose.yml -f apps-compose.yml up -d
echo ""
echo "DONE"
echo ""
echo "Emergency backup:"
echo "$EMERGENCY_BACKUP_FILE"
echo ""
echo "Check:"
echo " docker ps"
echo " curl http://localhost/health"