--- # version: "3.2.3" networks: wg: driver: bridge hs: driver: bridge volumes: caddy-data: caddy-share: certbot-lib: tailscale-lib: redis-data: mysql-lib: opengist-data: secrets: headscale.key: file: ~/.podsecrets/headscale.key root-mysql.pass: file: ~/.podsecrets/root-mysql.pass user-mysql.pass: file: ~/.podsecrets/user-mysql.pass email.pass: file: ~/.podsecrets/email.pass redis.pass: file: ~/.podsecrets/redis.pass # opengist.secret: # file: ~/.podsecrets/opengist.secret services: # @NOTE https://oneuptime.com/blog/post/2026-03-18-use-podman-containers-wireguard-vpn/view # @NOTE https://www.procustodibus.com/blog/2022/10/wireguard-in-podman/ wgclient: image: lscr.io/linuxserver/wireguard:latest container_name: wgclient cap_add: - SYS_MODULE - NET_ADMIN # - NET_RAW restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - /lib/modules:/lib/modules:ro - ~/.wg/containerized:/config/wg-confs:Z networks: - wg hostname: wgnet ports: - 51820:51820 - 51820:51820/udp sysctls: - net.ipv4.ip_forward=1 - net.ipv4.conf.all.src_valid_mark=1 - net.ipv6.conf.all.forwarding=1 # - net.ipv6.conf.all.src_valid_mark=1 env_file: - ${HOME}/.all.env labels: glance.name: Wireguard glance.id: wireguard glance.icon: "si:wireguard" glance.description: VPN client connection # @NOTE https://tailscale.com/docs/features/containers/docker # @NOTE https://tailscale.com/blog/docker-tailscale-guide tailclient: image: tailscale/tailscale:latest container_name: tailclient cap_add: - SYS_MODULE - NET_ADMIN restart: unless-stopped devices: - /dev/net/tun:/dev/net/tun volumes: - /etc/localtime:/etc/localtime:ro - /lib/modules:/lib/modules:ro - "tailscale-lib:/var/lib/tailscale" - ~/.config/tailscale:/config:Z networks: - hs hostname: tailnet env_file: - ${HOME}/.all.env # - ${HOME}/.tailscale.env environment: TS_AUTHKEY_FILE: /run/secrets/headscale.key TS_SERVE_CONFIG: /config/conf.json TS_EXTRA_ARGS: "--advertise-tags=tag:container" TS_STATE_DIR: /var/lib/tailscale secrets: - headscale.key # @TODO make subsequent containers have 'network_mode' attrbute set to value 'service:wgclient'/'service:tailclient' # OR make subsequent containers have 'networks' attribute set to list value with 'container:wgclient'/'contaner:tailclient' item cache0: image: redis:trixie container_name: cache0 restart: unless-stopped expose: - 6379 volumes: - /etc/localtime:/etc/localtime:ro - "redis-data:/data:z" - ~/.config/redis:/etc/redis:Z networks: - wg depends_on: - wgclient env_file: - ${HOME}/.all.env entrypoint: ["redis-server", "--save 60 1", "--loglevel warning", "/etc/redis/redis.conf"] labels: glance.name: Redis glance.id: redis glance.icon: "si:redis" glance.description: "Data structure cache and document/vector query server" # @NOTE https://hub.docker.com/_/mysql db0: image: mysql:lts container_name: db0 restart: unless-stopped expose: - 3306 volumes: - /etc/localtime:/etc/localtime:ro # @TODO use Ansible to adjust/edit configuration below # @NOTE https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html - ~/.config/mysql:/etc/mysql/conf.d:Z - mysql-lib:/var/lib/mysql networks: - wg depends_on: - wgclient env_file: - ${HOME}/.all.env - ${HOME}/.mysql.env environment: MYSQL_ROOT_PASSWORD_FILE: /run/secrets/root-mysql.pass MYSQL_USER: ${MYSQL_DB_USER:-admin} # @TODO create secret for the below, or leave it to Ansible # @NOTE https://github.com/docker-library/docs/blob/master/nextcloud/README.md#docker-secrets MYSQL_PASSWORD_FILE: /run/secrets/user-mysql.pass MYSQL_DATABASE: ${MYSQL_DB_NAME:-testdb} secrets: - "root-mysql.pass" - "user-mysql.pass" labels: glance.name: MySQL glance.id: mysql glance.icon: "si:mysql" glance.description: Database management server # @NOTE https://hub.docker.com/_/nextcloud cloud: image: nextcloud:stable-fpm container_name: cloud restart: unless-stopped expose: - 9000 volumes: - /etc/localtime:/etc/localtime:ro - ~/srv/${NEXTCLOUD_SUBDOMAIN}.${SERVER_FQDN}:/var/www/html:z networks: - wg depends_on: - cache0 - db0 - wgclient env_file: - ${HOME}/.all.env - ${HOME}/.email.env - ${HOME}/.mysql.env - ${HOME}/.nextcloud.env environment: REDIS_HOST: cache0 REDIS_HOST_PASSWORD_FILE: /run/secrets/redis.pass MYSQL_HOST: "${MYSQL_DB_HOST}:3306" MYSQL_DATABASE: ${NEXTCLOUD_DB_NAME:-nextcloud} MYSQL_USER: ${MYSQL_DB_USER:-admin} MYSQL_PASSWORD_FILE: /run/secrets/user-mysql.pass SMTP_HOST: ${EMAIL_SMTP_HOST} SMTP_PORT: ${EMAIL_SMTP_PORT:-465} SMTP_SECURE: ${EMAIL_SMTP_SECURE:-ssl} SMTP_AUTHTYPE: ${EMAIL_SMTP_AUTHTYPE:-LOGIN} SMTP_NAME: ${EMAIL_SMTP_USERNAME} SMTP_PASSWORD_FILE: /run/secrets/email.pass MAIL_FROM_ADDRESS: ${EMAIL_SMTP_USER_ALIAS:-admin} MAIL_DOMAIN: ${EMAIL_SMTP_EMAIL_ALIAS} # @NOTE https://docs.nextcloud.com/server/latest/admin_manual/configuration_server/reverse_proxy_configuration.html APACHE_DISABLE_REWRITE_IP: ${NEXTCLOUD_APACHE_DISABLE_REWRITE_IP:-1} TRUSTED_PROXIES: ${NEXTCLOUD_TRUSTED_PROXIES} NEXTCLOUD_TRUSTED_DOMAINS: ${NEXTCLOUD_SUBDOMAIN}.${SERVER_FQDN} # OVERWRITEHOST: ${NEXTCLOUD_HOST_REWRITE:?Enter the hostname or public FQDN for this server} OVERWRITECLIURL: ${NEXTCLOUD_URL_REWRITE} OVERWRITEPROTOCOL: ${NEXTCLOUD_PROTOCOL_REWRITE} secrets: - "user-mysql.pass" - email.pass - redis.pass labels: glance.name: Nextcloud glance.id: nextcloud glance.icon: "si:nextcloud" glance.url: "${SERVER_FQDN_SCHEME}://${NEXTCLOUD_SUBDOMAIN}.${SERVER_FQDN}" glance.description: "WebDAV/CardDAV/CalDAV cloud server" # @NOTE https://docs.gitea.com/installation/install-with-docker-rootless # @NOTE https://oneuptime.com/blog/post/2026-03-18-run-gitea-podman-container/view # @NOTE https://docs.gitea.com/administration/reverse-proxies # @NOTE https://docs.gitea.com/administration/config-cheat-sheet forge: image: docker.gitea.com/gitea:1.26.4 container_name: forge restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - ~/.config/gitea:/data:z expose: - 3000 - ${GITEA_SSH_PORT:-2323} networks: - wg depends_on: - db0 - wgclient env_file: - ${HOME}/.all.env - ${HOME}/.email.env - ${HOME}/.mysql.env - ${HOME}/.gitea.env environment: GITEA_DEFAULT_RUN_USER: ${GITEA_MODE:-dev} GITEA_DEFAULT_APP_NAME: ${GITEA_NAME} GITEA_server_PROTOCOL: http GITEA_server_DOMAIN: ${GITEA_SUBDOMAIN}.${SERVER_FQDN} # @NOTE https://gist.github.com/erik-toth/087262f19941da9bf4c2ce449fe98a47 GITEA_server_SSH_PORT: ${GITEA_SSH_PORT:-2323} GITEA_server_SSH_EXPOSE_ANONYMOUS: "false" GITEA_server_START_SSH_SERVER: "false" GITEA_server_LANDING_PAGE: ${GITEA_LANDING:-explore} GITEA_admin_DEFAULT_EMAIL_NOTIFICATIONS: onmention GITEA_security_REVERSE_PROXY_TRUSTED_PROXIES: ${GITEA_TRUSTED_PROXIES} GITEA_security_PASSWORD_COMPLEXITY: lower,upper,digit,spec GITEA_security_PASSWORD_CHECK_PWN: "true" GITEA_service_REGISTER_EMAIL_CONFIRM: "true" GITEA_service_DISABLE_REGISTRATION: ${GITEA_PROHIBIT_REGISTRATION:-false} GITEA_service_DEFAULT_KEEP_EMAIL_PRIVATE: "true" GITEA_service_ENABLE_NOTIFY_MAIL: "true" GITEA_picture_REPOSITORY_AVATAR_FALLBACK: image GITEA_picture_REPOSITORY_AVATAR_FALLBACK_IMAGE: img/repo_default.svg GITEA_log_MODE: file GITEA_log_ENABLE_SSH_LOG: "true" GITEA_mailer_ENABLED: "true" GITEA_mailer_PROTOCOL: ${EMAIL_SEND_PROTOCOL:-smtp}s GITEA_mailer_SMTP_ADDR: ${EMAIL_SMTP_HOST} GITEA_mailer_SMTP_PORT: ${EMAIL_SMTP_PORT:-465} GITEA_mailer_USER: ${EMAIL_SMTP_USERNAME} GITEA_mailer_PASSWD_FILE: /run/secrets/email.pass GITEA_mailer_FROM: ${EMAIL_SMTP_USER_ALIAS:-admin}@${EMAIL_SMTP_EMAIL_ALIAS} GITEA_database_DB_TYPE: ${GITEA_DB_TYPE:-mysql} GITEA_database_HOST: "${MYSQL_DB_HOST}:3306" GITEA_database_NAME: ${GITEA_DB_NAME:-gitea} GITEA_database_USER: ${MYSQL_DB_USER:-admin} GITEA_database_PASSWD_FILE: /run/secrets/user-mysql.pass GITEA_repository_DEFAULT_BRANCH: main GITEA_repository_DEFAULT_PRIVATE: private GITEA_repository_ORG_MAX_CREATION_LIMIT: 75 GITEA_repository_ENABLE_PUSH_CREATE_USER: "true" GITEA_repository_DEFAULT_CLOSE_ISSUES_VIA_COMMITS_IN_ANY_BRANCH: "true" GITEA_repository.issue_MAX_PINNED: 6 GITEA_federation_ENABLED: "true" secrets: - "user-mysql.pass" - email.pass labels: glance.name: Gitea glance.id: gitea glance.icon: "si:gitea" glance.url: "${SERVER_FQDN_SCHEME}://${GITEA_SUBDOMAIN}.${SERVER_FQDN}" glance.description: Git version control forge server gist: image: ghcr.io/thomiceli/opengist:1 container_name: gist restart: unless-stopped volumes: - /etc/localtime:/etc/localtime:ro - opengist-data:/opengist:z expose: - 6157 - ${OG_SSH_PORT:-2323} networks: - wg depends_on: - db0 - wgclient env_file: - ${HOME}/.all.env - ${HOME}/.mysql.env environment: OG_OPENGIST_HOME: /opengist OG_LOG_OUTPUT: file OG_GIT_DEFAULT_BRANCH: main OG_HTTP_GIT_ENABLED: "true" OG_EXTERNAL_URL: "${SERVER_FQDN_SCHEME}://${OG_SUBDOMAIN}.${SERVER_FQDN}" OG_CUSTOM_NAME: ${OG_NAME} OG_CUSTOM_LOGO: ${OG_LOGO:-logo.svg} OG_CUSTOM_FAVICON: ${OG_FAVICON:-logo.ico} secrets: - "user-mysql.pass" # - opengist.secret labels: glance.name: OpenGist glance.id: opengist glance.icon: "si:opengist" glance.url: "${SERVER_FQDN_SCHEME}://${OG_SUBDOMAIN}.${SERVER_FQDN}" glance.description: Pastebin server # @NOTE https://hub.docker.com/_/caddy/ # @NOTE https://blog.genxnotes.com/en/tech/how-to-move-the-hugo-public-folder-outside-the-project-root/ # @NOTE https://www.turtlestoffel.com/My-Quartz-Configuration#explorer-component-with-custom-content-folder revproxy0: image: caddy:latest container_name: revproxy0 cap_add: - NET_ADMIN restart: unless-stopped expose: - 80 - 443 - 443/udp volumes: - /etc/localtime:/etc/localtime:ro - ~/.config/caddy:/etc/caddy:Z - ~/srv/${SERVER_FQDN}:/srv/${SERVER_FQDN}:z - ~/srv/notes.${SERVER_FQDN}:/srv/notes.${SERVER_FQDN}:z - ~/srv/blog.${SERVER_FQDN}:/srv/blog.${SERVER_FQDN}:z - ~/srv/certbot.${SERVER_FQDN}:/srv/certbot.${SERVER_FQDN}:ro,z - "caddy-share:/usr/share/caddy" - "caddy-data:/data:z" - ~/.caddy:/config:Z volumes_from: - cloud:ro networks: - wg depends_on: - wgclient env_file: - ${HOME}/.all.env labels: glance.name: Caddy glance.id: caddy glance.icon: "si:caddy" glance.url: "${SERVER_FQDN_SCHEME}://${SERVER_FQDN}" glance.description: HTTPS reverse proxy server # @NOTE https://github.com/nbraun1/certbot sslcerts: image: nbraun1/certbot container_name: sslcerts restart: on-failure volumes: - /etc/localtime:/etc/localtime:ro - ~/.config/letsencrypt:/etc/letsencrypt:z - "certbot-lib:/var/lib/letsencrypt" # - ~/srv/certbot.${SERVER_FQDN}:/srv/certbot.${SERVER_FQDN}:z volumes_from: - revproxy0:rw networks: - wg depends_on: - revproxy0 - wgclient env_file: - ${HOME}/.all.env - ${HOME}/.certbot.env environment: EMAIL: ${CERTBOT_EMAIL} DOMAINS: ${CERTBOT_CHALLENGED_DOMAINS:-"${SERVER_FQDN},*.${SERVER_FQDN}"} AUTHENTICATOR: ${CERTBOT_AUTHENTICATOR} WEBROOT_PATH: ${SERVER_WEBROOT_PATH} ISSUANCE_TIMEOUT: 300 CRON: ${CERTBOT_CRON} # entrypoint: ["certonly"] dash: image: glanceapp/glance container_name: dash restart: unless-stopped expose: - 8080 volumes: - /etc/localtime:/etc/localtime:ro # Optionally, also mount docker socket if you want to use the docker containers widget - /var/run/docker.sock:/var/run/docker.sock:ro # @NOTE https://github.com/glanceapp/glance/blob/main/docs/configuration.md#configuring-glance - ~/.config/glance:/app/config:Z # @NOTE internal container server port is changed via 'glance.yml' config file; default is 8080 - ~/.local/glance:/app/assets:Z networks: - hs depends_on: - tailclient # @NOTE https://github.com/glanceapp/glance/blob/main/docs/configuration.md#environment-variables labels: glance.name: Self glance.id: self glance.icon: "si:glance" # glance.url: "${SERVER_MAGICDN_SCHEME}://${SERVER_MAGICDN}" glance.description: Dashboard # @NOTE https://github.com/glanceapp/glance/blob/main/docs/configuration.md#docker-containers # @TODO apply labels to each container that allows it to show up in Glance dashboard # @NOTE The following is a list of additional public-facing container services to add # - http://www.proftpd.org/, https://hub.docker.com/r/instantlinux/proftpd # - https://burp.grke.org/, https://hub.docker.com/r/pschiffe/burp-server # - https://rsync.samba.org/, https://hub.docker.com/r/vimagick/rsyncd # - https://shlink.io/, https://shlink.io/documentation/install-docker-image/ # - https://www.funkwhale.audio/, https://docs.funkwhale.audio/administrator/installation/docker.html # - https://join-lemmy.org/, https://join-lemmy.org/docs/administration/install_docker.html # - https://nodebb.org/, https://docs.nodebb.org/installing/cloud/docker/ # - https://joinbookwyrm.com/, https://docs.joinbookwyrm.com/install-prod.html # - https://github.com/FuzzyGrim/Yamtrack # - https://misskey-hub.net/en/, https://misskey-hub.net/en/docs/for-admin/install/guides/docker/ # - https://akkoma.social/, https://docs.akkoma.dev/stable/ # - https://hub.docker.com/r/instantlinux/proftpd # - https://prosody.im/, https://prosody.im/download/ # - https://element-hq.github.io/synapse/latest/setup/installation.html # - https://www.inspircd.org/, https://hub.docker.com/r/inspircd/inspircd-docker # - https://hub.docker.com/r/dnomd343/syncplay # - https://hub.docker.com/r/p3terx/aria2-pro # - https://github.com/SurgeDM/Surge#5-server-mode-with-docker-compose # - https://www.bookstackapp.com/, https://www.bookstackapp.com/docs/admin/installation/#docker # - https://moodle.org/ # - https://asciinema.org/ # - https://isso-comments.de/ # - https://shibumi.dev/posts/how-to-setup-your-own-wkd-server/ # - https://dario.griffo.io/posts/ultimate-guide-debian-repository-hosting/ # - https://gitlab.com/fdroid/docker-executable-fdroidserver # @NOTE The following is a list of additional private container services to add # - https://www.keycloak.org/, https://www.keycloak.org/server/containers # - https://tasktrove.io/, https://docs.tasktrove.io/installation#option-2-docker-compose # - https://github.com/dohsimpson/HabitTrove, https://github.com/dohsimpson/HabitTrove#docker-deployment # - https://grocy.info/, https://hub.docker.com/r/linuxserver/grocy # - https://mealie.io/, https://docs.mealie.io/documentation/getting-started/installation/installation-checklist/#step-3-customizing-the-docker-composeyaml-files # - https://actualbudget.org/, https://actualbudget.org/docs/install/docker # - https://sugoi.gitbook.io/lanraragi, https://sugoi.gitbook.io/lanraragi/installing-lanraragi/docker # - https://komga.org/, https://komga.org/docs/installation/docker # - https://github.com/janeczku/calibre-web, https://hub.docker.com/r/linuxserver/calibre-web # - https://www.kavitareader.com/, https://wiki.kavitareader.com/installation/docker/ # - https://immich.app/, https://docs.immich.app/install/docker-compose # - https://papra.app/en/, https://docs.papra.app/self-hosting/using-docker-compose/ # - https://stashapp.cc/, https://docs.stashapp.cc/installation/docker/ # - https://droposs.org/, https://droposs.org/docs/admin/quickstart/ # - https://jellyfin.org/, https://jellyfin.org/docs/general/installation/container # - https://papra.app/en/, https://docs.papra.app/self-hosting/using-docker-compose/ # - https://docs.paperless-ngx.com/, https://docs.paperless-ngx.com/setup/#docker # - https://atomicserver.eu/, https://docs.atomicdata.dev/atomic-data-overview # - https://github.com/sassanix/warracker # - https://github.com/cmintey/wishlist # - https://ghostfolio.com