atlas-os/deploy/install.sh
Atlas Developer 8c1efe6e30 feat: Atlas OS v2.0 — space-grade animated README, full productified repo
- assets/header.svg: animated SVG header (twinkling stars, orbiting service dots,
  Atlas A logo with glow, float/pulse animations, corner accents)
- README.md: animated banner, full 39-app service catalog, Mermaid architecture,
  AI stack table, tech stack, quick-deploy, repo structure, security model
- ARCHITECTURE.md: one-box philosophy, 5-tier service layers, data flow diagram,
  Caddy SSO pattern, AI mesh topology, Docker Compose topology
- SERVICES.md: all 55 containers + 20 systemd services documented
- CHANGELOG.md: full build history from v0.5 to v2.0
- assets/logo.svg: Atlas A logo with gradient
- deploy/install.sh: one-command installer (Docker + Caddy + Tailscale + stacks)
- deploy/compose/atlas-core.yml: Authentik + Nextcloud + Stalwart + Forgejo + Vaultwarden
- deploy/caddy/Caddyfile.template: Authentik SSO pattern, sanitized
- deploy/README.md: full deployment guide
- server/: sanitized atlas_brain.py, cockpit_shim.py, intelligence.py, meridian.py,
  atlas_router_api.py, cli-atlas.py (all secrets stripped, env var patterns)
- server/systemd/: 6 atlas-* service unit files
- server/README.md: deployment and configuration guide

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:33:18 +02:00

171 lines
9.9 KiB
Bash
Executable file

#!/usr/bin/env bash
# ╔═══════════════════════════════════════════════════════════════╗
# ║ ATLAS OS — ONE-COMMAND INSTALLER ║
# ║ github.com/atlascorporation/atlas-os ║
# ╚═══════════════════════════════════════════════════════════════╝
set -euo pipefail
# ── Colors ──────────────────────────────────────────────────────
RED='\033[0;31m'; GRN='\033[0;32m'; YLW='\033[1;33m'
BLU='\033[0;34m'; PRP='\033[0;35m'; CYN='\033[0;36m'
WHT='\033[1;37m'; RST='\033[0m'
ok() { echo -e " ${GRN}${RST} $1"; }
warn() { echo -e " ${YLW}${RST} $1"; }
err() { echo -e " ${RED}${RST} $1"; exit 1; }
step() { echo -e "\n${BLU}${RST} ${WHT}$1${RST}"; }
# ── Banner ───────────────────────────────────────────────────────
echo -e "${PRP}"
cat << 'BANNER'
█████╗ ████████╗██╗ █████╗ ███████╗ ██████╗ ███████╗
██╔══██╗╚══██╔══╝██║ ██╔══██╗██╔════╝ ██╔═══██╗██╔════╝
███████║ ██║ ██║ ███████║███████╗ ██║ ██║███████╗
██╔══██║ ██║ ██║ ██╔══██║╚════██║ ██║ ██║╚════██║
██║ ██║ ██║ ███████╗██║ ██║███████║ ╚██████╔╝███████║
╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝
BANNER
echo -e "${RST}"
echo -e " ${CYN}Your business on one box — space grade.${RST}"
echo ""
# ── Args ─────────────────────────────────────────────────────────
DOMAIN="${1:-}"
EMAIL="${2:-}"
INSTALL_DIR="${3:-/opt/atlas-os}"
for arg in "$@"; do
case "$arg" in
--domain=*) DOMAIN="${arg#*=}" ;;
--email=*) EMAIL="${arg#*=}" ;;
--dir=*) INSTALL_DIR="${arg#*=}" ;;
--domain) shift; DOMAIN="$1" ;;
--email) shift; EMAIL="$1" ;;
esac
done
[ -z "$DOMAIN" ] && read -rp " Domain (e.g. example.com): " DOMAIN
[ -z "$EMAIL" ] && read -rp " Admin email: " EMAIL
[[ "$DOMAIN" =~ \. ]] || err "Invalid domain: $DOMAIN"
[[ "$EMAIL" =~ @ ]] || err "Invalid email: $EMAIL"
# ── Preflight ────────────────────────────────────────────────────
step "Preflight checks"
[[ $EUID -eq 0 ]] || err "Run as root: sudo $0"
command -v apt-get &>/dev/null || err "Requires a Debian/Ubuntu system"
[[ $(uname -m) == "x86_64" ]] || warn "Tested on x86_64 — other arches may need adjustments"
ok "Running as root on Debian/Ubuntu x86_64"
ok "Domain: $DOMAIN · Email: $EMAIL"
# ── System update ────────────────────────────────────────────────
step "Updating system packages"
apt-get update -qq && apt-get upgrade -y -qq
apt-get install -y -qq curl wget git jq python3 python3-pip unzip ca-certificates gnupg lsb-release
ok "System packages updated"
# ── Docker ───────────────────────────────────────────────────────
step "Installing Docker"
if command -v docker &>/dev/null; then
ok "Docker already installed ($(docker --version | cut -d' ' -f3 | tr -d ','))"
else
curl -fsSL https://get.docker.com | sh
systemctl enable --now docker
ok "Docker installed"
fi
docker compose version &>/dev/null || { apt-get install -y docker-compose-plugin; ok "Docker Compose plugin installed"; }
# ── Caddy ────────────────────────────────────────────────────────
step "Installing Caddy"
if command -v caddy &>/dev/null; then
ok "Caddy already installed"
else
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' > /etc/apt/sources.list.d/caddy-stable.list
apt-get update -qq && apt-get install -y -qq caddy
ok "Caddy installed"
fi
# ── Tailscale ────────────────────────────────────────────────────
step "Installing Tailscale"
if command -v tailscale &>/dev/null; then
ok "Tailscale already installed"
else
curl -fsSL https://tailscale.com/install.sh | sh
warn "Run: tailscale up --accept-routes (then re-run this installer)"
fi
# ── Directory structure ───────────────────────────────────────────
step "Creating /opt/atlas directory structure"
mkdir -p "$INSTALL_DIR"/{compose,caddy,data,secrets,scripts,logs}
mkdir -p /opt/atlas/{brain,cockpit,data,cache,operations}
chmod 700 /opt/atlas/secrets
ok "Directory structure created at $INSTALL_DIR"
# ── Copy compose files ────────────────────────────────────────────
step "Deploying compose stacks"
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
cp "$REPO_DIR/deploy/compose/atlas-core.yml" "$INSTALL_DIR/compose/"
cp "$REPO_DIR/deploy/compose/atlas-ai.yml" "$INSTALL_DIR/compose/" 2>/dev/null || true
ok "Compose files staged at $INSTALL_DIR/compose/"
# ── Caddy config ─────────────────────────────────────────────────
step "Generating Caddy configuration"
sed "s/{DOMAIN}/$DOMAIN/g; s/{EMAIL}/$EMAIL/g" \
"$REPO_DIR/deploy/caddy/Caddyfile.template" > /etc/caddy/Caddyfile
caddy validate --config /etc/caddy/Caddyfile && ok "Caddyfile valid"
# ── Generate secrets ─────────────────────────────────────────────
step "Generating secrets"
SECRET_FILE="/opt/atlas/secrets/atlas.env"
if [ ! -f "$SECRET_FILE" ]; then
cat > "$SECRET_FILE" << ENVEOF
# Atlas OS — generated secrets
# DO NOT commit this file
POSTGRES_PASSWORD=$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 32)
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 48)
NEXTCLOUD_ADMIN_PASSWORD=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)
VAULTWARDEN_ADMIN_TOKEN=$(openssl rand -base64 32 | tr -dc 'A-Za-z0-9' | head -c 32)
DOMAIN=$DOMAIN
ADMIN_EMAIL=$EMAIL
ENVEOF
chmod 600 "$SECRET_FILE"
ok "Secrets generated at $SECRET_FILE (600)"
else
ok "Secrets file already exists — skipping"
fi
# ── Start core services ───────────────────────────────────────────
step "Starting core services"
cd "$INSTALL_DIR/compose"
docker compose -f atlas-core.yml --env-file "$SECRET_FILE" up -d
ok "Core services started"
# ── Start Caddy ───────────────────────────────────────────────────
step "Starting Caddy"
systemctl enable --now caddy
caddy reload --config /etc/caddy/Caddyfile
ok "Caddy running and config reloaded"
# ── Copy server scripts ───────────────────────────────────────────
step "Deploying Atlas Brain and server scripts"
cp "$REPO_DIR/server/"*.py /opt/atlas/ 2>/dev/null || warn "No server scripts found in repo server/"
cp "$REPO_DIR/server/systemd/"*.service /etc/systemd/system/ 2>/dev/null || true
systemctl daemon-reload
ok "Server scripts deployed to /opt/atlas/"
# ── Done ─────────────────────────────────────────────────────────
echo ""
echo -e "${GRN}╔═══════════════════════════════════════════════════════╗${RST}"
echo -e "${GRN}║ ATLAS OS INSTALLED SUCCESSFULLY ║${RST}"
echo -e "${GRN}╚═══════════════════════════════════════════════════════╝${RST}"
echo ""
echo -e " ${WHT}Post-install checklist:${RST}"
echo -e " ${CYN}1.${RST} Point DNS for $DOMAIN and *.${DOMAIN} → this server's IP"
echo -e " ${CYN}2.${RST} Open https://auth.${DOMAIN} → complete Authentik setup wizard"
echo -e " ${CYN}3.${RST} Create your Authentik admin user"
echo -e " ${CYN}4.${RST} Open https://command.${DOMAIN}/os/ → Atlas OS desktop"
echo -e " ${CYN}5.${RST} Configure atlas_brain.py mail accounts in /opt/atlas/"
echo -e " ${CYN}6.${RST} Enable Banking: connect bank accounts at https://fidi.${DOMAIN}"
echo ""
echo -e " ${YLW}Secrets stored at:${RST} $SECRET_FILE (chmod 600)"
echo -e " ${YLW}Logs:${RST} journalctl -u caddy -f | docker compose logs -f"
echo ""