Files
EZ-Homelab/docker-compose/productivity.yml
kelin f0a3907002 Round 4 improvements: automated config, relative paths, simplified deployment
- Automate Traefik email substitution in deploy script
- Auto-generate Authelia admin password (saved to ADMIN_PASSWORD.txt)
- Standardize all volume paths to use relative paths (./service/config)
- Switch Traefik to HTTP challenge by default (DNS challenge optional)
- Update documentation with improved setup instructions
- Enhance troubleshooting guide
- Update AGENT_INSTRUCTIONS with new conventions
- Simplify .env.example with clearer guidance

These changes reduce manual configuration steps and improve deployment reliability.
2026-01-13 18:30:06 -05:00

325 lines
10 KiB
YAML

# Productivity and Content Management Services
# Place in /opt/stacks/productivity/docker-compose.yml
services:
# Nextcloud - File sync and collaboration
# Access at: https://nextcloud.${DOMAIN}
nextcloud:
image: nextcloud:latest
container_name: nextcloud
restart: unless-stopped
networks:
- homelab-network
- traefik-network
- nextcloud-network
volumes:
- /opt/stacks/nextcloud/html:/var/www/html
- /mnt/nextcloud-data:/var/www/html/data # Large data on separate drive
environment:
- MYSQL_HOST=nextcloud-db
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
- NEXTCLOUD_ADMIN_USER=${NEXTCLOUD_ADMIN_USER:-admin}
- NEXTCLOUD_ADMIN_PASSWORD=${NEXTCLOUD_ADMIN_PASSWORD}
- NEXTCLOUD_TRUSTED_DOMAINS=${DOMAIN}
- TRUSTED_PROXIES=172.18.0.0/16
- OVERWRITEPROTOCOL=https
depends_on:
- nextcloud-db
labels:
- "homelab.category=productivity"
- "homelab.description=File sync and collaboration"
- "traefik.enable=true"
- "traefik.http.routers.nextcloud.rule=Host(`nextcloud.${DOMAIN}`)"
- "traefik.http.routers.nextcloud.entrypoints=websecure"
- "traefik.http.routers.nextcloud.tls.certresolver=letsencrypt"
- "traefik.http.routers.nextcloud.middlewares=authelia@docker"
- "traefik.http.services.nextcloud.loadbalancer.server.port=80"
nextcloud-db:
image: mariadb:10.11
container_name: nextcloud-db
restart: unless-stopped
networks:
- nextcloud-network
volumes:
- nextcloud-db-data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=nextcloud
- MYSQL_USER=nextcloud
- MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD}
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
labels:
- "homelab.category=productivity"
- "homelab.description=Nextcloud database"
# Mealie - Recipe manager
# Access at: https://mealie.${DOMAIN}
mealie:
image: ghcr.io/mealie-recipes/mealie:latest
container_name: mealie
restart: unless-stopped
networks:
- homelab-network
- traefik-network
volumes:
- /opt/stacks/mealie/data:/app/data
environment:
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
- TZ=${TZ}
- BASE_URL=https://mealie.${DOMAIN}
- DB_ENGINE=sqlite
labels:
- "homelab.category=productivity"
- "homelab.description=Recipe manager and meal planner"
- "traefik.enable=true"
- "traefik.http.routers.mealie.rule=Host(`mealie.${DOMAIN}`)"
- "traefik.http.routers.mealie.entrypoints=websecure"
- "traefik.http.routers.mealie.tls.certresolver=letsencrypt"
- "traefik.http.services.mealie.loadbalancer.server.port=9000"
# No Authelia - family members should access easily
# WordPress - Blog/website platform
# Access at: https://blog.${DOMAIN}
wordpress:
image: wordpress:latest
container_name: wordpress
restart: unless-stopped
networks:
- homelab-network
- traefik-network
- wordpress-network
volumes:
- /opt/stacks/wordpress/html:/var/www/html
environment:
- WORDPRESS_DB_HOST=wordpress-db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}
- WORDPRESS_DB_NAME=wordpress
depends_on:
- wordpress-db
labels:
- "homelab.category=productivity"
- "homelab.description=Blog and website platform"
- "traefik.enable=true"
- "traefik.http.routers.wordpress.rule=Host(`blog.${DOMAIN}`)"
- "traefik.http.routers.wordpress.entrypoints=websecure"
- "traefik.http.routers.wordpress.tls.certresolver=letsencrypt"
- "traefik.http.services.wordpress.loadbalancer.server.port=80"
# No Authelia - public blog
wordpress-db:
image: mariadb:10.11
container_name: wordpress-db
restart: unless-stopped
networks:
- wordpress-network
volumes:
- wordpress-db-data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${WORDPRESS_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=${WORDPRESS_DB_PASSWORD}
labels:
- "homelab.category=productivity"
- "homelab.description=WordPress database"
# Gitea - Self-hosted Git service
# Access at: https://git.${DOMAIN}
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
networks:
- homelab-network
- traefik-network
- gitea-network
volumes:
- /opt/stacks/gitea/data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
environment:
- USER_UID=${PUID:-1000}
- USER_GID=${PGID:-1000}
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=gitea-db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${GITEA_DB_PASSWORD}
depends_on:
- gitea-db
labels:
- "homelab.category=productivity"
- "homelab.description=Self-hosted Git service"
- "traefik.enable=true"
- "traefik.http.routers.gitea.rule=Host(`git.${DOMAIN}`)"
- "traefik.http.routers.gitea.entrypoints=websecure"
- "traefik.http.routers.gitea.tls.certresolver=letsencrypt"
- "traefik.http.routers.gitea.middlewares=authelia@docker"
- "traefik.http.services.gitea.loadbalancer.server.port=3000"
gitea-db:
image: postgres:14-alpine
container_name: gitea-db
restart: unless-stopped
networks:
- gitea-network
volumes:
- gitea-db-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD}
- POSTGRES_DB=gitea
labels:
- "homelab.category=productivity"
- "homelab.description=Gitea database"
# DokuWiki - Wiki without database
# Access at: https://wiki.${DOMAIN}
dokuwiki:
image: lscr.io/linuxserver/dokuwiki:latest
container_name: dokuwiki
restart: unless-stopped
networks:
- homelab-network
- traefik-network
volumes:
- ./$(basename $file .yml)/config:/config
environment:
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
- TZ=${TZ}
labels:
- "homelab.category=productivity"
- "homelab.description=File-based wiki"
- "traefik.enable=true"
- "traefik.http.routers.dokuwiki.rule=Host(`wiki.${DOMAIN}`)"
- "traefik.http.routers.dokuwiki.entrypoints=websecure"
- "traefik.http.routers.dokuwiki.tls.certresolver=letsencrypt"
- "traefik.http.routers.dokuwiki.middlewares=authelia@docker"
- "traefik.http.services.dokuwiki.loadbalancer.server.port=80"
# BookStack - Documentation platform
# Access at: https://docs.${DOMAIN}
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
restart: unless-stopped
networks:
- homelab-network
- traefik-network
- bookstack-network
volumes:
- ./$(basename $file .yml)/config:/config
environment:
- PUID=${PUID:-1000}
- PGID=${PGID:-1000}
- APP_URL=https://docs.${DOMAIN}
- DB_HOST=bookstack-db
- DB_PORT=3306
- DB_DATABASE=bookstack
- DB_USERNAME=bookstack
- DB_PASSWORD=${BOOKSTACK_DB_PASSWORD}
depends_on:
- bookstack-db
labels:
- "homelab.category=productivity"
- "homelab.description=Documentation and wiki platform"
- "traefik.enable=true"
- "traefik.http.routers.bookstack.rule=Host(`docs.${DOMAIN}`)"
- "traefik.http.routers.bookstack.entrypoints=websecure"
- "traefik.http.routers.bookstack.tls.certresolver=letsencrypt"
- "traefik.http.routers.bookstack.middlewares=authelia@docker"
- "traefik.http.services.bookstack.loadbalancer.server.port=80"
bookstack-db:
image: mariadb:10.11
container_name: bookstack-db
restart: unless-stopped
networks:
- bookstack-network
volumes:
- bookstack-db-data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=bookstack
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=${BOOKSTACK_DB_PASSWORD}
labels:
- "homelab.category=productivity"
- "homelab.description=BookStack database"
# MediaWiki - Wiki platform
# Access at: https://mediawiki.${DOMAIN}
mediawiki:
image: mediawiki:latest
container_name: mediawiki
restart: unless-stopped
networks:
- homelab-network
- traefik-network
- mediawiki-network
volumes:
- /opt/stacks/mediawiki/images:/var/www/html/images
- /opt/stacks/mediawiki/LocalSettings.php:/var/www/html/LocalSettings.php
environment:
- MEDIAWIKI_DB_HOST=mediawiki-db
- MEDIAWIKI_DB_NAME=mediawiki
- MEDIAWIKI_DB_USER=mediawiki
- MEDIAWIKI_DB_PASSWORD=${MEDIAWIKI_DB_PASSWORD}
depends_on:
- mediawiki-db
labels:
- "homelab.category=productivity"
- "homelab.description=MediaWiki platform"
- "traefik.enable=true"
- "traefik.http.routers.mediawiki.rule=Host(`mediawiki.${DOMAIN}`)"
- "traefik.http.routers.mediawiki.entrypoints=websecure"
- "traefik.http.routers.mediawiki.tls.certresolver=letsencrypt"
- "traefik.http.routers.mediawiki.middlewares=authelia@docker"
- "traefik.http.services.mediawiki.loadbalancer.server.port=80"
mediawiki-db:
image: mariadb:10.11
container_name: mediawiki-db
restart: unless-stopped
networks:
- mediawiki-network
volumes:
- mediawiki-db-data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=${MEDIAWIKI_DB_ROOT_PASSWORD}
- MYSQL_DATABASE=mediawiki
- MYSQL_USER=mediawiki
- MYSQL_PASSWORD=${MEDIAWIKI_DB_PASSWORD}
labels:
- "homelab.category=productivity"
- "homelab.description=MediaWiki database"
volumes:
nextcloud-db-data:
wordpress-db-data:
gitea-db-data:
bookstack-db-data:
mediawiki-db-data:
networks:
homelab-network:
external: true
traefik-network:
external: true
nextcloud-network:
driver: bridge
wordpress-network:
driver: bridge
gitea-network:
driver: bridge
bookstack-network:
driver: bridge
mediawiki-network:
driver: bridge