services:
  
  # Homepage App
  homepage-changemaker:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage-changemaker
    ports:
      - 3010:3000
    volumes:
      - ./configs/homepage:/app/config
      - ./assets/icons:/app/public/icons
      - ./assets/images:/app/public/images
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - HOMEPAGE_ALLOWED_HOSTS=*
    restart: unless-stopped
    networks:
      - changemaker

  # n8n - Workflow Automation Tool
  n8n:
    image: docker.n8n.io/n8nio/n8n
    container_name: n8n-changemaker
    restart: unless-stopped
    ports:
      - "${N8N_PORT:-5678}:5678"
    environment:
      - N8N_HOST=${N8N_HOST:-n8n.${DOMAIN}}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${N8N_HOST:-n8n.${DOMAIN}}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE:-UTC}
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY:-changeMe}
      - N8N_USER_MANAGEMENT_DISABLED=false
      - N8N_DEFAULT_USER_EMAIL=${N8N_USER_EMAIL:-admin@example.com}
      - N8N_DEFAULT_USER_PASSWORD=${N8N_USER_PASSWORD:-changeMe}
    volumes:
      - n8n_data:/home/node/.n8n
      - ./local-files:/files
    networks:
      - changemaker

  # OpenWebUI - AI Chat Interface
  open-webui:
    image: ghcr.io/open-webui/open-webui:main
    container_name: open-webui-changemaker
    ports:
      - "${OPEN_WEBUI_PORT:-3005}:8080"
    volumes:
      - open-webui:/app/backend/data
    extra_hosts:
      - "host.docker.internal:host-gateway"
    restart: unless-stopped
    networks:
      - changemaker
    depends_on:
      - ollama

  # Excalidraw services
  excalidraw:
    image: kiliandeca/excalidraw
    container_name: excalidraw-changemaker
    healthcheck:
      disable: true
    ports:
      - "${EXCALIDRAW_PORT:-3333}:80"
    environment:
      BACKEND_V2_GET_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2/scenes/
      BACKEND_V2_POST_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2/scenes/
      LIBRARY_URL: ${EXCALIDRAW_LIBRARY_URL:-https://libraries.excalidraw.com}
      LIBRARY_BACKEND: ${EXCALIDRAW_LIBRARY_BACKEND:-https://us-central1-excalidraw-room-persistence.cloudfunctions.net/libraries}
      SOCKET_SERVER_URL: ${EXCALIDRAW_PUBLIC_SOCKET_URL:-http://localhost:3333}/
      STORAGE_BACKEND: "http"
      HTTP_STORAGE_BACKEND_URL: ${EXCALIDRAW_PUBLIC_URL:-http://localhost:3333}/api/v2
    restart: unless-stopped
    networks:
      - changemaker
    depends_on:
      - excalidraw-storage-backend
      - excalidraw-room
      - redis-excalidraw

  excalidraw-storage-backend:
    image: kiliandeca/excalidraw-storage-backend
    container_name: excalidraw-storage-backend-changemaker
    restart: unless-stopped
    environment:
      STORAGE_URI: redis://redis-excalidraw:6379
    networks:
      - changemaker
    depends_on:
      - redis-excalidraw

  excalidraw-room:
    image: excalidraw/excalidraw-room
    container_name: excalidraw-room-changemaker
    restart: unless-stopped
    networks:
      - changemaker

  redis-excalidraw:
    image: redis:6.2-alpine
    container_name: redis-excalidraw-changemaker
    restart: unless-stopped
    volumes:
      - redis_excalidraw_data:/data
    networks:
      - changemaker

  # listmonk app
  listmonk-app:
    image: listmonk/listmonk:latest
    container_name: listmonk_app
    restart: unless-stopped
    ports:
      - "9000:9000"
    networks:
      - changemaker
    hostname: ${LISTMONK_HOSTNAME}
    depends_on:
      - listmonk-db
    command: [sh, -c, "./listmonk --install --idempotent --yes --config '' && ./listmonk --upgrade --yes --config '' && ./listmonk --config ''"]
    environment:
      LISTMONK_app__address: 0.0.0.0:9000
      LISTMONK_db__user: ${POSTGRES_USER}
      LISTMONK_db__password: ${POSTGRES_PASSWORD}
      LISTMONK_db__database: ${POSTGRES_DB}
      LISTMONK_db__host: listmonk-db
      LISTMONK_db__port: 5432
      LISTMONK_db__ssl_mode: disable
      LISTMONK_db__max_open: 25
      LISTMONK_db__max_idle: 25
      LISTMONK_db__max_lifetime: 300s
      TZ: Etc/UTC
      LISTMONK_ADMIN_USER: ${LISTMONK_ADMIN_USER:-}
      LISTMONK_ADMIN_PASSWORD: ${LISTMONK_ADMIN_PASSWORD:-}
    volumes:
      - ./assets/uploads:/listmonk/uploads:rw

  # Postgres database
  listmonk-db:
    image: postgres:17-alpine
    container_name: listmonk-db
    restart: unless-stopped
    ports:
      - "0.0.0.0:5432:5432"
    networks:
      - changemaker
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 6
    volumes:
      - type: volume
        source: listmonk-data
        target: /var/lib/postgresql/data

  # Monica CRM
  monica-app:
    image: monica
    container_name: monica-app-changemaker
    depends_on:
      - monica-db
    ports:
      - 8085:80
    environment:
      - APP_KEY=${MONICA_APP_KEY}
      - DB_HOST=monica-db
      - DB_USERNAME=${MONICA_DB_USERNAME}
      - DB_PASSWORD=${MONICA_DB_PASSWORD}
    volumes:
      - data:/var/www/html/storage
    restart: unless-stopped
    networks:
      - changemaker

  # Monica Database
  monica-db:
    image: mariadb:11
    container_name: monica-db-changemaker
    environment:
      - MYSQL_RANDOM_ROOT_PASSWORD=true
      - MYSQL_DATABASE=${MONICA_MYSQL_DATABASE}
      - MYSQL_USER=${MONICA_MYSQL_USER}
      - MYSQL_PASSWORD=${MONICA_MYSQL_PASSWORD}
    volumes:
      - mysql:/var/lib/mysql
    restart: unless-stopped
    networks:
      - changemaker

  # MkDocs Documentation
  mkdocs:
    image: squidfunk/mkdocs-material
    container_name: markdown-editor-mkdocs-changemaker
    volumes:
      - ./mkdocs:/docs:rw
      - ./assets/images:/docs/assets/images:rw
    user: "${USER_ID:-1000}:${GROUP_ID:-1000}"
    ports:
      - "${MKDOCS_PORT:-4000}:8000"
    environment:
      - SITE_URL=${BASE_DOMAIN:-https://changeme.org}
    command: serve --dev-addr=0.0.0.0:8000 --watch-theme --livereload
    networks:
      - changemaker
    restart: unless-stopped

  mkdocs-site-server:
    image: lscr.io/linuxserver/nginx:latest
    container_name: mkdocs-site-server-changemaker
    environment:
      - PUID=${USER_ID:-1000}  # Uses USER_ID from your .env file, defaults to 1000
      - PGID=${GROUP_ID:-1000} # Uses GROUP_ID from your .env file, defaults to 1000
      - TZ=Etc/UTC
    volumes:
      - ./mkdocs/site:/config/www  # Mounts your static site to Nginx's web root
    ports:
      - "4001:80"  # Exposes Nginx's port 80 to host port 4001
    restart: unless-stopped
    networks:
      - changemaker

  # Flatnotes - Note-taking app
  flatnotes:
    container_name: flatnotes-changemaker
    image: dullage/flatnotes:latest
    environment:
      PUID: ${FLATNOTES_PUID:-1000}
      PGID: ${FLATNOTES_PGID:-1000}
      FLATNOTES_AUTH_TYPE: ${FLATNOTES_AUTH_TYPE:-password}
      FLATNOTES_USERNAME: ${FLATNOTES_USERNAME}
      FLATNOTES_PASSWORD: ${FLATNOTES_PASSWORD}
      FLATNOTES_SECRET_KEY: ${FLATNOTES_SECRET_KEY}
    volumes:
      - ./mkdocs/docs/blog/posts:/data
    ports:
      - "${FLATNOTES_PORT:-8080}:8080"
    restart: unless-stopped
    networks:
      - changemaker

  code-server:
    build:
      context: .
      dockerfile: Dockerfile.code-server
    container_name: code-server-changemaker
    environment:
      - DOCKER_USER=${USER_NAME:-coder}
      - DEFAULT_WORKSPACE=/home/coder/mkdocs
    user: "${USER_ID:-1000}:${GROUP_ID:-1000}"
    volumes:
      - ./configs/code-server/.config:/home/coder/.config
      - ./configs/code-server/.local:/home/coder/.local
      - ./mkdocs:/home/coder/mkdocs/
    ports:
      - "${CODE_SERVER_PORT:-8888}:8080"
    restart: unless-stopped
    networks:
      - changemaker

  ollama:
    image: ollama/ollama
    container_name: ollama-changemaker
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]
    volumes:
      - ollama:/root/.ollama
    ports:
      - "11435:11434"
    restart: unless-stopped
    networks:
      - changemaker

  # Gitea - Git service
  gitea-app:
    image: docker.gitea.com/gitea:1.23.7
    container_name: gitea_changemaker
    environment:
      - USER_UID=${USER_ID}
      - USER_GID=${GROUP_ID}
      - GITEA__database__DB_TYPE=${GITEA_DB_TYPE}
      - GITEA__database__HOST=${GITEA_DB_HOST}
      - GITEA__database__NAME=${GITEA_DB_NAME}
      - GITEA__database__USER=${GITEA_DB_USER}
      - GITEA__database__PASSWD=${GITEA_DB_PASSWD}
      - GITEA__server__ROOT_URL=${GITEA_ROOT_URL}
      - GITEA__server__HTTP_PORT=${GITEA_WEB_PORT}
      - GITEA__server__PROTOCOL=http
      - GITEA__server__DOMAIN=${GITEA_DOMAIN}
      - GITEA__server__ENABLE_GZIP=true
      - GITEA__server__PROXY_PROTOCOL=true
      - GITEA__server__PROXY_PROXY_PROTOCOL_TLS=true
      - GITEA__server__PROXY_ALLOW_SUBNET=0.0.0.0/0
    restart: always
    networks:
      - gitea
    volumes:
      - gitea_data:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "${GITEA_WEB_PORT}:3030"
      - "${GITEA_SSH_PORT}:22"
    depends_on:
      - gitea-db

  gitea-db:
    image: mysql:8
    container_name: gitea_mysql_changemaker
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${GITEA_DB_ROOT_PASSWORD}
      - MYSQL_USER=${GITEA_DB_USER}
      - MYSQL_PASSWORD=${GITEA_DB_PASSWD}
      - MYSQL_DATABASE=${GITEA_DB_NAME}
    networks:
      - gitea
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${GITEA_DB_USER}", "-p${GITEA_DB_PASSWD}"]
      interval: 10s
      timeout: 5s
      retries: 5

  portainer:
    image: portainer/portainer-ce:lts
    container_name: portainer-changemaker
    restart: always
    environment:
      - DISABLE_HTTP_REDIRECT=true
    networks:
      - changemaker
    ports:
      - "8005:8000"
      - "9444:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

  # Mini-QR - QR Code Generator
  mini-qr:
    image: ghcr.io/lyqht/mini-qr:latest
    container_name: mini-qr
    ports:
      - 8081:8080
    restart: unless-stopped
    networks:
      - changemaker

  # Ferdium - Multiple messaging app client
  ferdium:
    image: lscr.io/linuxserver/ferdium:latest
    container_name: ferdium-changemaker
    security_opt:
      - seccomp:unconfined #optional
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - CUSTOM_PORT=3009
      - CUSTOM_HTTPS_PORT=3006
    volumes:
      - ./configs/ferdium:/config
    ports:
      - 3009:3009
      - 3006:3006
    shm_size: "1gb"
    restart: unless-stopped
    networks:
      - changemaker

  # Apache Answer - Q&A Platform
  answer:
    image: apache/answer
    container_name: answer-changemaker
    restart: unless-stopped
    environment:
      - DB_TYPE=sqlite3
      - PAGINATION_PAGE_SIZE=10
      - LANGUAGE=en-US
      - TZ=Etc/UTC
    ports:
      - "${ANSWER_APP_PORT:-9080}:80"
    volumes:
      - ./answer-data:/data
    networks:
      - changemaker

  # NocoDB - Open Source Airtable Alternative
  nocodb: 
    depends_on: 
      root_db: 
        condition: service_healthy
    environment: 
      NC_DB: "pg://root_db:5432?u=postgres&p=password&d=root_db"
    image: "nocodb/nocodb:latest"
    ports: 
      - "8090:8080"
    restart: always
    volumes: 
      - "nc_data:/usr/app/data"
    networks:
      - changemaker
  root_db: 
    environment: 
      POSTGRES_DB: root_db
      POSTGRES_PASSWORD: password
      POSTGRES_USER: postgres
    healthcheck: 
      interval: 10s
      retries: 10
      test: "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""
      timeout: 2s
    image: postgres:16.6
    restart: always
    volumes: 
      - "db_data:/var/lib/postgresql/data"
    networks:
      - changemaker

  # ConvertX - File Conversion Tool
  convertx: 
    image: ghcr.io/c4illin/convertx
    container_name: convertx-changemaker
    restart: unless-stopped
    ports:
      - "${CONVERTX_PORT:-3100}:3000"
    environment:
      - JWT_SECRET=${CONVERTX_JWT_SECRET:-aLongAndSecretStringUsedToSignTheJSONWebToken1234}
    volumes:
      - ./convertx-data:/app/data
    networks:
      - changemaker

  # Rocket.Chat - Team Chat Platform
  rocketchat:
    image: ${ROCKETCHAT_IMAGE:-registry.rocket.chat/rocketchat/rocket.chat}:${ROCKETCHAT_RELEASE:-latest}
    container_name: rocketchat-changemaker
    restart: unless-stopped
    environment:
      MONGO_URL: "mongodb://${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}:${ROCKETCHAT_MONGODB_PORT:-27017}/${ROCKETCHAT_MONGODB_DATABASE:-rocketchat}?replicaSet=${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}"
      MONGO_OPLOG_URL: "mongodb://${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}:${ROCKETCHAT_MONGODB_PORT:-27017}/local?replicaSet=${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}"
      ROOT_URL: ${ROCKETCHAT_ROOT_URL:-http://localhost:${ROCKETCHAT_PORT:-3004}}
      PORT: ${ROCKETCHAT_CONTAINER_PORT:-3000}
      DEPLOY_METHOD: docker
      DEPLOY_PLATFORM: ${ROCKETCHAT_DEPLOYMENT_ENVIRONMENT:-changemaker}
    ports:
      - "${ROCKETCHAT_PORT:-3004}:${ROCKETCHAT_CONTAINER_PORT:-3000}"
    depends_on:
      - mongodb-rocketchat
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:${ROCKETCHAT_CONTAINER_PORT:-3000}/api/info"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s
    networks:
      - changemaker
  
  # MongoDB for Rocket.Chat
  mongodb-rocketchat:
    image: docker.io/bitnami/mongodb:${ROCKETCHAT_MONGODB_VERSION:-6.0}
    container_name: mongodb-rocketchat-changemaker
    restart: unless-stopped
    volumes:
      - mongodb_rocketchat_data:/bitnami/mongodb
    environment:
      MONGODB_REPLICA_SET_MODE: primary
      MONGODB_REPLICA_SET_NAME: ${ROCKETCHAT_MONGODB_REPLICA_SET:-rs0}
      MONGODB_PORT_NUMBER: ${ROCKETCHAT_MONGODB_PORT:-27017}
      MONGODB_INITIAL_PRIMARY_HOST: ${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}
      MONGODB_INITIAL_PRIMARY_PORT_NUMBER: ${ROCKETCHAT_MONGODB_PORT:-27017}
      MONGODB_ADVERTISED_HOSTNAME: ${ROCKETCHAT_MONGODB_HOST:-mongodb-rocketchat}
      MONGODB_ENABLE_JOURNAL: ${ROCKETCHAT_MONGODB_ENABLE_JOURNAL:-true}
      ALLOW_EMPTY_PASSWORD: ${ROCKETCHAT_MONGODB_ALLOW_EMPTY_PASSWORD:-yes}
    networks:
      - changemaker

networks:
  changemaker:
    driver: bridge
  gitea:
    external: false

volumes:
  listmonk-data:
  data:
    name: data
  mysql:
    name: mysql
  ollama:
  gitea_data:
    driver: local
  mysql_data:
    driver: local
  portainer_data:
    name: portainer_data_changemaker
  redis_excalidraw_data:
    driver: local
  open-webui:
    driver: local
  notused:
  nocodb_db_data:
    driver: local
  n8n_data:
    driver: local
  mongodb_rocketchat_data:
    driver: local
  db_data: {}
  nc_data: {}



