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
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,17 @@ cd docker

### Configure and start

1. Set the fully qualified domain name (use `chat.example.org` or your own domain):
1. Set the fully qualified domain name and email (use `chat.example.org` or your own domain):

```bash
echo 'MAIL_DOMAIN=chat.example.org' > .env
echo 'ACME_EMAIL=admin@example.org' >> .env
```

**Environment variables:**
- `MAIL_DOMAIN`: Your fully qualified domain name (required)
- `ACME_EMAIL`: Email for Let's Encrypt notifications (recommended)

The container generates a `chatmail.ini` with defaults from `MAIL_DOMAIN` on first start.
To customize chatmail settings, mount your own `chatmail.ini` instead
(see [Custom chatmail.ini](#custom-chatmailiini) below).
Expand Down Expand Up @@ -213,6 +218,58 @@ in `docker-compose.override.yaml`.
Changed certificates are picked up automatically via inotify. See the examples in
`docker-compose.override.yaml.example` for details.

## Troubleshooting

### ACME agreement prompt error

If you encounter an error like:

```
acme.interactor: interaction auto-responder couldn't give a canned response:
unknown unique ID, cannot respond: "acme-agreement:https://letsencrypt.org/..."
cannot prompt the user: currently non-interactive; try running without --batch flag
```

This means acmetool cannot prompt for Let's Encrypt agreement acceptance in the non-interactive Docker environment.

**Solution 1: Set ACME_EMAIL in .env (automatic)**

If you set `ACME_EMAIL` in your `.env` file, the container will automatically accept the ACME terms during initialization:

```bash
# Add email to .env
echo 'ACME_EMAIL=admin@example.org' >> .env

# Restart container to apply
docker compose down
docker compose up -d
```

The container init script will automatically:
1. Create the ACME responses file with your email
2. Accept Let's Encrypt terms
3. Obtain TLS certificates

**Solution 2: Manual fix with fix-acme-agreement.sh**

If the container is already running and you need to fix it manually:

```bash
# Download and run the helper script
wget https://raw.githubusercontent.com/chatmail/docker/main/scripts/fix-acme-agreement.sh
chmod +x fix-acme-agreement.sh

# Run with email from .env or provide directly
./fix-acme-agreement.sh
# or: ./fix-acme-agreement.sh admin@example.org
```

No container restart required with this method.

**Alternative: Use external TLS certificates**

If you prefer to manage certificates outside the container (e.g., with certbot on the host), see [External TLS certificates](#external-tls-certificates) above.

## Migrating from a bare-metal install

If you have an existing bare-metal chatmail installation and want to switch to Docker:
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.override.yaml.example
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ services:
# - ./scripts/entrypoint.sh:/entrypoint.sh

# environment:
## Auto-accept ACME terms with provided email (reads from .env):
# ACME_EMAIL: "${ACME_EMAIL}"
##
## Mount certs (above) and set TLS_EXTERNAL_CERT_AND_KEY to in-container paths.
## A tls-cert-reload.path watcher inside the container reloads services
## when the cert file changes. However, inotify does not cross bind-mount
Expand Down
1 change: 1 addition & 0 deletions env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
MAIL_DOMAIN=chat.example.com
ACME_EMAIL=admin@example.com
18 changes: 18 additions & 0 deletions scripts/chatmail-init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,24 @@ else
echo "$current_fp" > "$FINGERPRINT_FILE"
fi

# Auto-fix ACME agreement acceptance if email is provided
if [ -n "${ACME_EMAIL:-}" ]; then
echo "[INFO] Auto-configuring ACME with email: $ACME_EMAIL"
cat > /var/lib/acme/conf/responses << ACME_EOF
"acme-enter-email": "$ACME_EMAIL"
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.7-June-04-2026.pdf": true
"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.8-July-06-2026.pdf": true
ACME_EOF

# Trigger certificate reconciliation
if command -v acmetool >/dev/null 2>&1; then
echo "[INFO] Running acmetool reconcile with accepted terms"
acmetool reconcile --batch 2>&1 | while IFS= read -r line; do
echo "[INFO] acmetool: $line"
done || echo "[WARN] acmetool reconcile failed, will retry via timer"
fi
fi

# Signal success to Docker healthcheck
touch /run/chatmail-init.done

Expand Down
38 changes: 38 additions & 0 deletions scripts/fix-acme-agreement.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/bash
# Fix ACME agreement acceptance in running chatmail container
# Usage: ./fix-acme-agreement.sh [email] [container_name]

set -e

ACME_EMAIL="${1}"
CONTAINER_NAME="${2:-chatmail}"

# Try to load email from .env if not provided
if [ -z "$ACME_EMAIL" ] && [ -f .env ]; then
ACME_EMAIL=$(grep -E "^ACME_EMAIL=" .env | cut -d'=' -f2- | tr -d '"' | tr -d "'")
fi

if [ -z "$ACME_EMAIL" ]; then
echo "Error: Email address required"
echo "Usage: $0 <email> [container_name]"
echo " or: Set ACME_EMAIL in .env file"
exit 1
fi

echo "==> Creating ACME responses file in container: $CONTAINER_NAME"
echo " Email: $ACME_EMAIL"

docker exec "$CONTAINER_NAME" bash -c "cat > /var/lib/acme/conf/responses << \"EOF\"
\"acme-enter-email\": \"$ACME_EMAIL\"
\"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.7-June-04-2026.pdf\": true
\"acme-agreement:https://letsencrypt.org/documents/LE-SA-v1.8-July-06-2026.pdf\": true
EOF"

echo "==> ACME responses file created successfully"

echo "==> Running acmetool reconcile to obtain certificates..."

docker exec "$CONTAINER_NAME" acmetool reconcile --batch

echo "==> Done! Check certificate status with:"
echo " docker exec $CONTAINER_NAME acmetool status"