version: '3.3' services: # Reverse Proxy - Caddy for routing all .cell traffic caddy: image: caddy:2-alpine container_name: cell-caddy ports: - "80:80" - "443:443" volumes: - ./config/caddy/Caddyfile:/etc/caddy/Caddyfile - ./data/caddy:/data - ./config/caddy/certs:/config/caddy/certs restart: unless-stopped cap_add: - NET_ADMIN networks: cell-network: ipv4_address: 172.20.0.2 # DNS Server - CoreDNS for .cell TLD resolution dns: image: coredns/coredns:latest container_name: cell-dns command: ["-conf", "/etc/coredns/Corefile"] ports: - "53:53/udp" - "53:53/tcp" volumes: - ./config/dns/Corefile:/etc/coredns/Corefile - ./data/dns:/data restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.3 # DHCP Server - dnsmasq for IP leasing dhcp: image: alpine:latest container_name: cell-dhcp ports: - "67:67/udp" volumes: - ./config/dhcp/dnsmasq.conf:/etc/dnsmasq.conf - ./data/dhcp:/var/lib/misc restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.4 command: ["/bin/sh", "-c", "apk add --no-cache dnsmasq && dnsmasq -d -C /etc/dnsmasq.conf"] cap_add: - NET_ADMIN # NTP Server - chrony for time synchronization ntp: image: alpine:latest container_name: cell-ntp ports: - "123:123/udp" volumes: - ./config/ntp/chrony.conf:/etc/chrony/chrony.conf restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.5 cap_add: - SYS_TIME command: ["/bin/sh", "-c", "apk add --no-cache chrony && rm -f /var/run/chrony/chronyd.pid && exec chronyd -d -f /etc/chrony/chrony.conf -n"] # Email Server - Postfix + Dovecot mail: image: mailserver/docker-mailserver:latest container_name: cell-mail hostname: mail domainname: cell.local env_file: ./config/mail/mailserver.env ports: - "25:25" - "587:587" - "993:993" volumes: - ./data/maildata:/var/mail - ./data/mailstate:/var/mail-state - ./data/maillogs:/var/log/mail - ./config/mail/config:/tmp/docker-mailserver/ - ./config/mail/ssl:/etc/letsencrypt restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.6 cap_add: - NET_ADMIN # Calendar & Contacts - Radicale radicale: image: tomsquest/docker-radicale:latest container_name: cell-radicale ports: - "5232:5232" volumes: - ./config/radicale:/etc/radicale - ./data/radicale:/data restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.7 # File Storage - WebDAV webdav: image: bytemark/webdav:latest container_name: cell-webdav ports: - "8080:80" environment: - AUTH_TYPE=Basic - USERNAME=admin - PASSWORD=admin123 volumes: - ./data/files:/var/lib/dav restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.8 # WireGuard VPN wireguard: image: linuxserver/wireguard:latest container_name: cell-wireguard environment: - SERVERMODE=true - PUID=911 - PGID=911 ports: - "51820:51820/udp" volumes: - ./config/wireguard:/config - /lib/modules:/lib/modules restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.9 cap_add: - NET_ADMIN - SYS_MODULE sysctls: - net.ipv4.conf.all.src_valid_mark=1 - net.ipv4.ip_forward=1 # API Server api: build: ./api container_name: cell-api ports: - "3000:3000" volumes: - ./data/api:/app/data - ./data/dns:/app/data/dns - ./config/api:/app/config - ./config/wireguard:/app/config/wireguard - ./config/dns:/app/config/dns - /var/run/docker.sock:/var/run/docker.sock pid: host restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.10 depends_on: - wireguard - dns # Web UI - React + Vite webui: build: ./webui container_name: cell-webui ports: - "8081:80" restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.11 # Webmail - RainLoop rainloop: image: hardware/rainloop container_name: cell-rainloop restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.12 ports: - "8888:8888" volumes: - ./data/rainloop:/rainloop/data # File Manager - FileGator filegator: image: filegator/filegator container_name: cell-filegator restart: unless-stopped networks: cell-network: ipv4_address: 172.20.0.13 ports: - "8082:8080" volumes: - ./data/filegator:/var/www/filegator/private networks: cell-network: driver: bridge ipam: config: - subnet: 172.20.0.0/16