Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/docker-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ jobs:
sudo systemctl stop apparmor || true
sudo apparmor_parser -R /etc/apparmor.d/* 2>/dev/null || true
cmlxc init
cmlxc docker deploy dock0 --source ghcr:sha-${{ needs.build.outputs.relay_sha_short }}
cmlxc docker deploy dock0 --source ghcr:sha-${{ needs.build.outputs.relay_sha_short }} --compose https://raw.githubusercontent.com/chatmail/docker/${{ github.event.pull_request.head.sha || github.sha }}/docker-compose.yaml
cmlxc test-cmdeploy dock0

# test_trixie:
Expand All @@ -260,5 +260,5 @@ jobs:
# sudo systemctl stop apparmor || true
# sudo apparmor_parser -R /etc/apparmor.d/* 2>/dev/null || true
# cmlxc init
# cmlxc docker deploy dock0 --source ghcr:sha-${{ needs.build.outputs.relay_sha_short }}-trixie
# cmlxc docker deploy dock0 --source ghcr:sha-${{ needs.build.outputs.relay_sha_short }}-trixie --compose https://raw.githubusercontent.com/chatmail/docker/${{ github.event.pull_request.head.sha || github.sha }}/docker-compose.yaml
# cmlxc test-cmdeploy dock0
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,43 @@ git clone https://github.com/chatmail/docker
cd docker
```

### Building from source

The default configuration uses explicit port mappings and works with both `docker compose` and `podman-compose`.

`podman-compose up` builds the image locally by default, but the build needs
`cmdeploy/` and `chatmaild/` from [chatmail/relay](https://github.com/chatmail/relay):

- `git clone https://github.com/chatmail/relay` first, and then
- `git clone https://github.com/chatmail/docker relay/docker` to clone this repo inside it
- Run `podman-compose up -d` from `relay/docker`.

## Networking modes

The container can operate in two modes:

### Bridged mode (default, recommended)

Uses explicit port mappings and standard Docker bridging, only tested with
`docker compose`.

By default, client IPs never reach the services and thus can't/won't be logged
as Docker's userland-proxy terminates connections before they reach the
container's network stack. It can be disabled host-wide wide by
setting`"userland-proxy": false` in `/etc/docker/daemon.json`, see
[docs](https://docs.docker.com/reference/cli/dockerd/#daemon-configuration-file)).

Publishing ports in bridged mode implies Docker inserting its iptables rules
ahead of of anything an operator may set up, so be aware.

### Host mode (alternative)

Gives container near-host-level network access without port mappings.

```bash
docker compose -f docker-compose.yaml -f docker-compose.host-mode.yaml up -d
```

### Configure and start

1. Set the fully qualified domain name (use `chat.example.org` or your own domain):
Expand Down
9 changes: 9 additions & 0 deletions docker-compose.host-mode.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Alternative compose override for host networking mode, giving direct network access to the container.
#
# Run with: docker compose -f docker-compose.yaml -f docker-compose.host-mode.yaml up

services:
chatmail:
network_mode: "host"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j4n after some thought from our chats, my research, and things i've ran into. i think it's likely a better approach to just use network_mode: host for a singular compose stack vs giving user options of bridging.

reason: bridging can get complex really fast with something like chatmail. plus without manipulating the daemon you theoretically lose the client-ip.

# Host mode requires cgroup:host for systemd.
cgroup: host
21 changes: 11 additions & 10 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,8 @@
# volumes, env overrides) in docker-compose.override.yaml instead.
# See docker-compose.override.yaml.example in this directory for a starting point.
#
# Security notes: this container uses
# - network_mode:host chatmail needs many ports (25, 53, 80, 143, 443, 465,
# 587, 993, 3340, 8443) and needs to operate from the real IP, which bridging
# would make tricky
# - cgroup:host (required for systemd).
# Together these give the container near-host-level access. This is acceptable
# for a dedicated mail server, but be aware that the container can bind any
# port and see all host network traffic.

# Network mode: Bridged with port mappings
# cgroup:host required for systemd.
services:
chatmail:
build:
Expand Down Expand Up @@ -40,7 +33,15 @@ services:
environment:
MAIL_DOMAIN: $MAIL_DOMAIN
ACME_EMAIL: ${ACME_EMAIL:-}
network_mode: "host"
ports:
- "25:25"
- "80:80"
- "143:143"
- "443:443"
- "465:465"
- "587:587"
- "993:993"
- "3340:3340"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j4n looks like you aren't exposing the turn port

you want something like this:

turn_port = 3478
turn_min_port = 49152
turn_max_port = 65535

then in compose.yaml

  - "3478:3478/udp"
  - "49152-65535:49152-65535/udp"

reason: turn will start to enumerate ports so it's best practice allow large udp ranges for this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j4n also it's best practice if you're going to use bridge-mode explicitly define the bridge

networks:
  default:
    enable_ipv6: true

this network can be whatever you want namespace wise ie chatmail. consider adding the enable_ipv6: bool given that there's a lot of focus on ipv6 from experience.

volumes:
## system (required)
- /sys/fs/cgroup:/sys/fs/cgroup:rw
Expand Down