6 Commits

Author SHA1 Message Date
974a83fe6e web-app-bluesky: enable custom AppView domain and refactor DNS records
- Un-commented `view.bluesky.{{ PRIMARY_DOMAIN }}` in config to allow
  explicit AppView domain definition.
- Reworked `03_dns.yml` to build `cloudflare_records` list programmatically,
  including conditional addition of AppView records only if the domain is
  not `api.bsky.app`.
- Improved AAAA handling with `| default('')` and proper ternary
  expressions for `present/absent`.
- Updated `vars/main.yml` to remove default port fallback for
  `BLUESKY_VIEW_PORT`.

Refs: https://chatgpt.com/share/68cdde1d-1bd4-800f-a4bb-319372752fcd
2025-09-20 00:50:31 +02:00
0168167769 Docker: introduce docker-compose setup and simplify CMD
- Replaced ENTRYPOINT/CMD with a single CMD ["infinito --help"] in Dockerfile
- Added docker-compose.yml with service 'infinito', port bindings, volumes, networks
- Added env.sample for BIND_IP, SUBNET, GATEWAY defaults

See conversation: https://chatgpt.com/share/68cda4d5-1fe0-800f-a7f7-191cb8b70d84
2025-09-19 21:22:45 +02:00
1c7152ceb2 Solved build bug 2025-09-19 20:51:06 +02:00
2a98b265bc Reduced port exposal to local for better encapsulation 2025-09-19 19:43:16 +02:00
14d1362dc8 Removed alias from bookwyrm 2025-09-19 19:14:55 +02:00
a4a8061998 Refactor: unify Docker build config via build.yml.j2 include
Replaced duplicated inline build definitions in multiple docker-compose.yml.j2
templates with a shared include (roles/docker-container/templates/build.yml.j2).
This ensures consistent use of pull_policy: never and Dockerfile context across
services (Postgres, Bookwyrm, Bridgy Fed, Chess, Confluence, Jira, Moodle,
OpenProject, Pretix, Roulette Wheel, WordPress, XWiki, Simpleicons).

Conversation: https://chatgpt.com/share/68cd8f35-b764-800f-9b00-2c837103d2fb
2025-09-19 19:13:44 +02:00
25 changed files with 181 additions and 129 deletions

View File

@@ -64,6 +64,4 @@ RUN INFINITO_PATH=$(pkgmgr path infinito) && \
#RUN INFINITO_PATH=$(pkgmgr path infinito) && \
# cd "$INFINITO_PATH" && \
# make test
ENTRYPOINT ["infinito"]
CMD ["--help"]
CMD ["infinito --help"]

60
docker-compose.yml Normal file
View File

@@ -0,0 +1,60 @@
version: "3.9"
services:
infinito:
build:
context: .
dockerfile: Dockerfile
network: host
pull_policy: never
container_name: infinito_nexus
restart: unless-stopped
command: tail -f /dev/null
volumes:
- data:/var/lib/docker/volumes/
- backups:/Backups/
- letsencrypt:/etc/letsencrypt/
ports:
# --- Mail services (classic + secure) ---
- "${BIND_IP:-127.0.0.1}:25:25" # SMTP
- "${BIND_IP:-127.0.0.1}:110:110" # POP3
- "${BIND_IP:-127.0.0.1}:143:143" # IMAP
- "${BIND_IP:-127.0.0.1}:465:465" # SMTPS
- "${BIND_IP:-127.0.0.1}:587:587" # Submission (SMTP)
- "${BIND_IP:-127.0.0.1}:993:993" # IMAPS (bound to public IP)
- "${BIND_IP:-127.0.0.1}:995:995" # POP3S
- "${BIND_IP:-127.0.0.1}:4190:4190" # Sieve (ManageSieve)
# --- Web / API services ---
- "${BIND_IP:-127.0.0.1}:80:80" # HTTP
- "${BIND_IP:-127.0.0.1}:443:443" # HTTPS
- "${BIND_IP:-127.0.0.1}:8448:8448" # Matrix federation port
# --- TURN / STUN (UDP + TCP) ---
- "${BIND_IP:-127.0.0.1}:3478-3480:3478-3480/udp" # TURN/STUN UDP
- "${BIND_IP:-127.0.0.1}:3478-3480:3478-3480" # TURN/STUN TCP
# --- Streaming / RTMP ---
- "${BIND_IP:-127.0.0.1}:1935:1935" # Peertube
# --- Custom / application ports ---
- "${BIND_IP:-127.0.0.1}:2201:2201" # Gitea
- "${BIND_IP:-127.0.0.1}:2202:2202" # Gitlab
- "${BIND_IP:-127.0.0.1}:2203:22" # SSH
- "${BIND_IP:-127.0.0.1}:33552:33552"
# --- Consecutive ranges ---
- "${BIND_IP:-127.0.0.1}:48081-48083:48081-48083"
- "${BIND_IP:-127.0.0.1}:48087:48087"
volumes:
data:
backups:
letsencrypt:
networks:
default:
driver: bridge
ipam:
driver: default
config:
- subnet: ${SUBNET:-172.30.0.0/24}
gateway: ${GATEWAY:-172.30.0.1}

3
env.sample Normal file
View File

@@ -0,0 +1,3 @@
BIND_IP=127.0.0.1
SUBNET=172.30.0.0/24
GATEWAY=172.30.0.1

View File

@@ -0,0 +1,6 @@
{# integrate it into service sections to be build by Dockerfile #}
pull_policy: never
build:
context: .
dockerfile: Dockerfile
{# pass Arguments here #}

View File

@@ -3,10 +3,7 @@
postgres:
container_name: "{{ POSTGRES_CONTAINER }}"
image: "{{ POSTGRES_CUSTOM_IMAGE_NAME }}"
build:
context: .
dockerfile: Dockerfile
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
command:
- "postgres"
- "-c"

View File

@@ -7,7 +7,7 @@
volumes:
- data:/baserow/data
ports:
- "{{ ports.localhost.http[application_id] }}:80"
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"
{% include 'roles/docker-container/templates/networks.yml.j2' %}
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}

View File

@@ -13,7 +13,7 @@ server:
canonical:
web: "web.bluesky.{{ PRIMARY_DOMAIN }}"
api: "api.bluesky.{{ PRIMARY_DOMAIN }}"
# view: "view.bluesky.{{ PRIMARY_DOMAIN }}"
view: "view.bluesky.{{ PRIMARY_DOMAIN }}"
csp:
whitelist:
connect-src:

View File

@@ -1,80 +1,94 @@
---
# Creates Cloudflare DNS records for Bluesky:
# - PDS/API host (A/AAAA)
# - Handle TXT verification (_atproto)
# - Optional Web UI host (A/AAAA)
# - Optional custom AppView host (A/AAAA)
#
# Requirements:
# DNS_PROVIDER == 'cloudflare'
# CLOUDFLARE_API_TOKEN set
#
# Inputs (inventory/vars):
# BLUESKY_API_DOMAIN, BLUESKY_WEB_DOMAIN, BLUESKY_VIEW_DOMAIN
# BLUESKY_WEB_ENABLED (bool), BLUESKY_VIEW_ENABLED (bool)
# PRIMARY_DOMAIN
# networks.internet.ip4 (and optionally networks.internet.ip6)
- name: "DNS (Cloudflare) for Bluesky base records"
include_role:
name: sys-dns-cloudflare-records
when: DNS_PROVIDER | lower == 'cloudflare'
vars:
cloudflare_records:
# 1) PDS / API host
- type: A
zone: "{{ BLUESKY_API_DOMAIN | to_zone }}"
name: "{{ BLUESKY_API_DOMAIN }}"
content: "{{ networks.internet.ip4 }}"
solo: true
proxied: false
- type: AAAA
zone: "{{ BLUESKY_API_DOMAIN | to_zone }}"
name: "{{ BLUESKY_API_DOMAIN }}"
content: "{{ networks.internet.ip6 | default('') }}"
proxied: false
solo: true
state: "{{ (networks.internet.ip6 is defined and (networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}"
# 2) Handle verification for primary handle (Apex)
- type: TXT
zone: "{{ PRIMARY_DOMAIN | to_zone }}"
name: "_atproto.{{ PRIMARY_DOMAIN }}"
value: '"did=did:web:{{ BLUESKY_API_DOMAIN }}"'
solo: true
# 3) Web UI host (only if enabled)
- type: A
solo: true
zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}"
name: "{{ BLUESKY_WEB_DOMAIN }}"
content: "{{ networks.internet.ip4 }}"
proxied: true
state: "{{ (BLUESKY_WEB_ENABLED | bool) | ternary('present','absent') }}"
- type: AAAA
solo: true
zone: "{{ BLUESKY_WEB_DOMAIN | to_zone }}"
name: "{{ BLUESKY_WEB_DOMAIN }}"
content: "{{ networks.internet.ip6 | default('') }}"
proxied: true
state: "{{ (BLUESKY_WEB_ENABLED | bool) and (networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}"
# 4) Custom AppView host (only if you actually run one and it's not api.bsky.app)
- type: A
solo: true
zone: "{{ BLUESKY_VIEW_DOMAIN | to_zone }}"
name: "{{ BLUESKY_VIEW_DOMAIN }}"
content: "{{ networks.internet.ip4 }}"
proxied: false
state: "{{ (BLUESKY_VIEW_ENABLED | bool) and (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') | ternary('present','absent') }}"
- type: AAAA
solo: true
zone: "{{ BLUESKY_VIEW_DOMAIN | to_zone }}"
name: "{{ BLUESKY_VIEW_DOMAIN }}"
content: "{{ networks.internet.ip6 | default('') }}"
proxied: false
state: "{{ (BLUESKY_VIEW_ENABLED | bool) and (BLUESKY_VIEW_DOMAIN != 'api.bsky.app') and (networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0) | ternary('present','absent') }}"
cloudflare_records: >-
{{
[
{
'type': 'A',
'zone': (BLUESKY_API_DOMAIN | to_zone),
'name': BLUESKY_API_DOMAIN,
'content': networks.internet.ip4,
'solo': True,
'proxied': False,
},
{
'type': 'AAAA',
'zone': (BLUESKY_API_DOMAIN | to_zone),
'name': BLUESKY_API_DOMAIN,
'content': (networks.internet.ip6 | default('')),
'proxied': False,
'solo': True,
'state': (
((networks.internet.ip6 is defined) and ((networks.internet.ip6 | string) | length > 0))
| ternary('present','absent')
),
},
{
'type': 'TXT',
'zone': (PRIMARY_DOMAIN | to_zone),
'name': "_atproto.%s" % PRIMARY_DOMAIN,
'value': '"did=did:web:%s"' % BLUESKY_API_DOMAIN,
'solo': True,
},
{
'type': 'A',
'solo': True,
'zone': (BLUESKY_WEB_DOMAIN | to_zone),
'name': BLUESKY_WEB_DOMAIN,
'content': networks.internet.ip4,
'proxied': True,
'state': ((BLUESKY_WEB_ENABLED | bool) | ternary('present','absent')),
},
{
'type': 'AAAA',
'solo': True,
'zone': (BLUESKY_WEB_DOMAIN | to_zone),
'name': BLUESKY_WEB_DOMAIN,
'content': (networks.internet.ip6 | default('')),
'proxied': True,
'state': (
((BLUESKY_WEB_ENABLED | bool)
and (networks.internet.ip6 is defined)
and ((networks.internet.ip6 | string) | length > 0))
| ternary('present','absent')
),
},
]
+
(
(BLUESKY_VIEW_DOMAIN != 'api.bsky.app')
| ternary([
{
'type': 'A',
'solo': True,
'zone': (BLUESKY_VIEW_DOMAIN | to_zone),
'name': BLUESKY_VIEW_DOMAIN,
'content': networks.internet.ip4,
'proxied': False,
'state': (
((BLUESKY_VIEW_ENABLED | bool))
| ternary('present','absent')
),
},
{
'type': 'AAAA',
'solo': True,
'zone': (BLUESKY_VIEW_DOMAIN | to_zone),
'name': BLUESKY_VIEW_DOMAIN,
'content': (networks.internet.ip6 | default('')),
'proxied': False,
'state': (
((BLUESKY_VIEW_ENABLED | bool)
and (networks.internet.ip6 is defined)
and ((networks.internet.ip6 | string) | length > 0))
| ternary('present','absent')
),
}
],
[])
)
}}

View File

@@ -30,7 +30,7 @@ BLUESKY_VIEW_ENABLED: "{{ applications | get_app_conf(application_id,
BLUESKY_VIEW_DOMAIN: "{{ domains[application_id].view if BLUESKY_VIEW_ENABLED else 'api.bsky.app' }}"
BLUESKY_VIEW_URL: "{{ WEB_PROTOCOL }}://{{ BLUESKY_VIEW_DOMAIN }}"
BLUESKY_VIEW_DID: "did:web:{{ BLUESKY_VIEW_DOMAIN }}"
BLUESKY_VIEW_PORT: "{{ ports.localhost.http['web-app-bluesky_view'] | default(8053) }}"
BLUESKY_VIEW_PORT: "{{ ports.localhost.http['web-app-bluesky_view'] }}"
## Server
BLUESKY_API_DOMAIN: "{{ domains[application_id].api }}"

View File

@@ -32,8 +32,7 @@ server:
domains:
canonical:
- "book.{{ PRIMARY_DOMAIN }}"
aliases:
- "bookwyrm.{{ PRIMARY_DOMAIN }}"
aliases: []
rbac:
roles: {}
registration_open: false

View File

@@ -9,9 +9,7 @@
(python manage.py initdb || true) &&
python -m gunicorn bookwyrm.wsgi:application --bind 0.0.0.0:{{ container_port }}
'
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: "{{ BOOKWYRM_CUSTOM_IMAGE }}"
container_name: "{{ BOOKWYRM_CONTAINER }}"
hostname: "{{ BOOKWYRM_HOSTNAME }}"
@@ -29,6 +27,7 @@
image: "{{ BOOKWYRM_CUSTOM_IMAGE }}"
container_name: "{{ BOOKWYRM_WORKER_CONTAINER }}"
command: "bash -lc 'celery -A celerywyrm worker -l INFO'"
pull_policy: never
volumes:
- 'data:/app/data'
- 'media:/app/media'

View File

@@ -1,9 +1,7 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
args:
BRIDGY_REPO_URL: "{{ BRIDGY_REPO_URL }}"
BRIDGY_REPO_BRANCH: "{{ BRIDGY_REPO_BRANCH }}"

View File

@@ -1,8 +1,6 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
args:
CHESS_VERSION: "{{ CHESS_VERSION }}"
CHESS_REPO_URL: "{{ CHESS_REPO_URL }}"

View File

@@ -1,8 +1,6 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: "{{ CONFLUENCE_CUSTOM_IMAGE }}"
container_name: "{{ CONFLUENCE_CONTAINER }}"
hostname: '{{ CONFLUENCE_HOSTNAME}}'

View File

@@ -1,9 +1,7 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: "{{ JIRA_CUSTOM_IMAGE }}"
container_name: "{{ JIRA_CONTAINER }}"
hostname: '{{ JIRA_HOSTNAME }}'

View File

@@ -3,10 +3,7 @@
moodle:
{% set container_port = 8080 %}
container_name: {{ moodle_container }}
build:
context: .
dockerfile: Dockerfile
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: moodle_custom
ports:
- 127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}

View File

@@ -5,7 +5,7 @@
command: --config /oauth2-proxy.cfg
hostname: oauth2-proxy
ports:
- {{ ports.localhost.oauth2_proxy[application_id] }}:4180/tcp
- 127.0.0.1:{{ ports.localhost.oauth2_proxy[application_id] }}:4180/tcp
volumes:
- "{{ docker_compose.directories.volumes }}{{ applications | get_app_conf('web-app-oauth2-proxy','configuration_file')}}:/oauth2-proxy.cfg"
{% endif %}

View File

@@ -3,10 +3,7 @@ x-op-app: &app
logging:
driver: journald
image: {{ openproject_custom_image }}
build:
context: .
dockerfile: Dockerfile
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
{% include 'roles/docker-compose/templates/base.yml.j2' %}
@@ -19,6 +16,7 @@ x-op-app: &app
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: {{ openproject_custom_image }}
container_name: {{ openproject_proxy_name }}
pull_policy: never
command: "./docker/prod/proxy"
ports:
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"

View File

@@ -8,7 +8,7 @@
- "data:/var/www/storage"
- "./env:/var/www/.env"
ports:
- "{{ ports.localhost.http[application_id] }}:80"
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %}
worker:

View File

@@ -1,8 +1,6 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: "{{ PRETIX_IMAGE_CUSTOM }}"
container_name: "{{ PRETIX_CONTAINER }}"
hostname: '{{ PRETIX_HOSTNAME}}'

View File

@@ -1,9 +1,7 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
container_name: roulette_application
build:
context: .
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
ports:
- 127.0.0.1:{{ ports.localhost.http[application_id] }}:8080
restart: {{ DOCKER_RESTART_POLICY }}

View File

@@ -3,9 +3,7 @@
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: {{ WORDPRESS_CUSTOM_IMAGE }}
container_name: {{ WORDPRESS_CONTAINER }}
build:
context: .
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
ports:
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:80"
volumes:

View File

@@ -1,8 +1,6 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: "{{ XWIKI_IMAGE_CUSTOM }}"
container_name: "{{ XWIKI_CONTAINER }}"
hostname: '{{ XWIKI_HOSTNAME}}'

View File

@@ -4,7 +4,7 @@
{% include 'roles/docker-container/templates/base.yml.j2' %}
image: coturn/coturn
restart: always
network_mode: "host" # Nutzt die Host-IP für externe Erreichbarkeit (optional)
network_mode: "host"
ports:
- "3478:3478/udp"
- "3478:3478/tcp"

View File

@@ -1,13 +1,10 @@
{% include 'roles/docker-compose/templates/base.yml.j2' %}
application:
build:
context: .
dockerfile: Dockerfile
pull_policy: never
{% include 'roles/docker-container/templates/build.yml.j2' %}
image: simpleicons-server:latest
container_name: simpleicons-server
ports:
- "{{ ports.localhost.http[application_id] }}:{{ container_port }}"
- 127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}
{% include 'roles/docker-container/templates/base.yml.j2' %}
{% include 'roles/docker-container/templates/networks.yml.j2' %}
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}