---
# 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]
