- 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>
213 lines
6.8 KiB
YAML
213 lines
6.8 KiB
YAML
---
|
|
# Atlas OS — Core Services Compose Stack
|
|
# Deploy: docker compose -f atlas-core.yml --env-file /opt/atlas/secrets/atlas.env up -d
|
|
#
|
|
# Services: Authentik (SSO), Nextcloud (files), Stalwart (mail),
|
|
# Forgejo (git), Vaultwarden (passwords)
|
|
#
|
|
# All services on internal network only — Caddy is the sole public entry point.
|
|
|
|
version: "3.8"
|
|
|
|
networks:
|
|
atlas-net:
|
|
external: false
|
|
driver: bridge
|
|
|
|
volumes:
|
|
ak-db-data:
|
|
ak-redis-data:
|
|
ak-media:
|
|
ak-certs:
|
|
ak-custom-templates:
|
|
nc-data:
|
|
nc-db-data:
|
|
nc-redis-data:
|
|
stalwart-data:
|
|
forgejo-data:
|
|
forgejo-db-data:
|
|
vault-data:
|
|
|
|
services:
|
|
|
|
# ─── Authentik SSO ────────────────────────────────────────────────────────
|
|
authentik-db:
|
|
image: docker.io/library/postgres:16-alpine
|
|
container_name: atlas-ak-db
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
POSTGRES_USER: authentik
|
|
POSTGRES_DB: authentik
|
|
volumes:
|
|
- ak-db-data:/var/lib/postgresql/data
|
|
networks: [atlas-net]
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U authentik"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
|
|
authentik-redis:
|
|
image: docker.io/library/redis:alpine
|
|
container_name: atlas-ak-redis
|
|
restart: unless-stopped
|
|
command: --save 60 1 --loglevel warning
|
|
volumes:
|
|
- ak-redis-data:/data
|
|
networks: [atlas-net]
|
|
|
|
authentik-server:
|
|
image: ghcr.io/goauthentik/server:latest
|
|
container_name: atlas-authentik-server
|
|
restart: unless-stopped
|
|
command: server
|
|
environment:
|
|
AUTHENTIK_REDIS__HOST: authentik-redis
|
|
AUTHENTIK_POSTGRESQL__HOST: authentik-db
|
|
AUTHENTIK_POSTGRESQL__USER: authentik
|
|
AUTHENTIK_POSTGRESQL__NAME: authentik
|
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASSWORD}
|
|
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
|
AUTHENTIK_ERROR_REPORTING__ENABLED: "false"
|
|
AUTHENTIK_EMAIL__FROM: admin@${DOMAIN}
|
|
volumes:
|
|
- ak-media:/media
|
|
- ak-custom-templates:/templates
|
|
- ak-certs:/certs
|
|
ports:
|
|
- "127.0.0.1:9000:9000"
|
|
- "127.0.0.1:9443:9443"
|
|
networks: [atlas-net]
|
|
depends_on: [authentik-db, authentik-redis]
|
|
|
|
authentik-worker:
|
|
image: ghcr.io/goauthentik/server:latest
|
|
container_name: atlas-authentik-worker
|
|
restart: unless-stopped
|
|
command: worker
|
|
environment:
|
|
AUTHENTIK_REDIS__HOST: authentik-redis
|
|
AUTHENTIK_POSTGRESQL__HOST: authentik-db
|
|
AUTHENTIK_POSTGRESQL__USER: authentik
|
|
AUTHENTIK_POSTGRESQL__NAME: authentik
|
|
AUTHENTIK_POSTGRESQL__PASSWORD: ${POSTGRES_PASSWORD}
|
|
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
|
AUTHENTIK_EMAIL__FROM: admin@${DOMAIN}
|
|
volumes:
|
|
- ak-media:/media
|
|
- ak-certs:/certs
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
networks: [atlas-net]
|
|
depends_on: [authentik-db, authentik-redis]
|
|
|
|
# ─── Nextcloud Files ──────────────────────────────────────────────────────
|
|
nextcloud-db:
|
|
image: docker.io/library/mariadb:11
|
|
container_name: atlas-nc-db
|
|
restart: unless-stopped
|
|
environment:
|
|
MYSQL_ROOT_PASSWORD: ${POSTGRES_PASSWORD}
|
|
MYSQL_DATABASE: nextcloud
|
|
MYSQL_USER: nextcloud
|
|
MYSQL_PASSWORD: ${POSTGRES_PASSWORD}
|
|
volumes:
|
|
- nc-db-data:/var/lib/mysql
|
|
networks: [atlas-net]
|
|
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
|
|
|
|
nextcloud-redis:
|
|
image: docker.io/library/redis:alpine
|
|
container_name: atlas-nc-redis
|
|
restart: unless-stopped
|
|
networks: [atlas-net]
|
|
|
|
nextcloud:
|
|
image: nextcloud:31-apache
|
|
container_name: atlas-nc-app
|
|
restart: unless-stopped
|
|
environment:
|
|
MYSQL_HOST: nextcloud-db
|
|
MYSQL_DATABASE: nextcloud
|
|
MYSQL_USER: nextcloud
|
|
MYSQL_PASSWORD: ${POSTGRES_PASSWORD}
|
|
NEXTCLOUD_ADMIN_USER: admin
|
|
NEXTCLOUD_ADMIN_PASSWORD: ${NEXTCLOUD_ADMIN_PASSWORD}
|
|
NEXTCLOUD_TRUSTED_DOMAINS: cloud.${DOMAIN}
|
|
REDIS_HOST: nextcloud-redis
|
|
OVERWRITEPROTOCOL: https
|
|
OVERWRITECLIURL: https://cloud.${DOMAIN}
|
|
volumes:
|
|
- nc-data:/var/www/html
|
|
ports:
|
|
- "127.0.0.1:8443:80"
|
|
networks: [atlas-net]
|
|
depends_on: [nextcloud-db, nextcloud-redis]
|
|
|
|
# ─── Stalwart Mail ────────────────────────────────────────────────────────
|
|
stalwart:
|
|
image: docker.io/stalwartlabs/mail-server:latest
|
|
container_name: atlas-stalwart
|
|
restart: unless-stopped
|
|
ports:
|
|
- "127.0.0.1:8080:8080" # web admin
|
|
- "25:25" # SMTP
|
|
- "465:465" # SMTPS
|
|
- "587:587" # Submission
|
|
- "993:993" # IMAPS
|
|
- "4190:4190" # Sieve
|
|
volumes:
|
|
- stalwart-data:/opt/stalwart-mail
|
|
networks: [atlas-net]
|
|
|
|
# ─── Forgejo Git ──────────────────────────────────────────────────────────
|
|
forgejo-db:
|
|
image: docker.io/library/postgres:16-alpine
|
|
container_name: atlas-forgejo-db
|
|
restart: unless-stopped
|
|
environment:
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
POSTGRES_USER: forgejo
|
|
POSTGRES_DB: forgejo
|
|
volumes:
|
|
- forgejo-db-data:/var/lib/postgresql/data
|
|
networks: [atlas-net]
|
|
|
|
forgejo:
|
|
image: codeberg.org/forgejo/forgejo:10
|
|
container_name: atlas-forgejo
|
|
restart: unless-stopped
|
|
environment:
|
|
USER_UID: "1000"
|
|
USER_GID: "1000"
|
|
FORGEJO__database__DB_TYPE: postgres
|
|
FORGEJO__database__HOST: forgejo-db:5432
|
|
FORGEJO__database__NAME: forgejo
|
|
FORGEJO__database__USER: forgejo
|
|
FORGEJO__database__PASSWD: ${POSTGRES_PASSWORD}
|
|
FORGEJO__server__DOMAIN: git.${DOMAIN}
|
|
FORGEJO__server__ROOT_URL: https://git.${DOMAIN}
|
|
volumes:
|
|
- forgejo-data:/data
|
|
ports:
|
|
- "127.0.0.1:3000:3000"
|
|
- "22:22"
|
|
networks: [atlas-net]
|
|
depends_on: [forgejo-db]
|
|
|
|
# ─── Vaultwarden Passwords ────────────────────────────────────────────────
|
|
vaultwarden:
|
|
image: vaultwarden/server:latest
|
|
container_name: atlas-vaultwarden
|
|
restart: unless-stopped
|
|
environment:
|
|
DOMAIN: https://vault.${DOMAIN}
|
|
ADMIN_TOKEN: ${VAULTWARDEN_ADMIN_TOKEN}
|
|
SIGNUPS_ALLOWED: "false"
|
|
INVITATIONS_ALLOWED: "true"
|
|
WEBSOCKET_ENABLED: "true"
|
|
volumes:
|
|
- vault-data:/data
|
|
ports:
|
|
- "127.0.0.1:8222:80"
|
|
networks: [atlas-net]
|