- 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>
171 lines
9.9 KiB
Bash
Executable file
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 ""
|