- gatus: status/uptime monitoring page with hot-reloaded config - mail-archiver: IMAP email archive and full-text search (postgres backend) - rustdesk: self-hosted remote desktop relay, cross-VLAN/FQDN docs - unifi: UniFi Network Application with MongoDB init via Docker configs - vaultwarden: Bitwarden-compatible password manager with SMTP prompts - watchyourlan: network device tracker (host networking for ARP scanning) All follow caddy_net container-routing pattern except rustdesk (raw TCP/UDP) and watchyourlan (network_mode: host, incompatible with caddy_net). README.md services table updated with all 6 new entries. https://claude.ai/code/session_01UZus2Q9gNTfUdqSMrhuX29
161 lines
5.7 KiB
Bash
161 lines
5.7 KiB
Bash
#!/bin/bash
|
|
# services/mail-archiver.sh — Mail Archiver (IMAP email archive & search).
|
|
# Part of the modular post-install system (sourced by setup.sh).
|
|
#
|
|
# Self-hosted email archive — connects to IMAP accounts, indexes messages,
|
|
# and provides full-text search. No big-tech email required.
|
|
# Image: s1t5/mailarchiver DB: postgres:17-alpine
|
|
|
|
register_service mail-archiver utilities "IMAP email archive & search (Mail Archiver)" 5000
|
|
|
|
install_mail-archiver() {
|
|
require_docker || return 1
|
|
log_info "Installing Mail Archiver..."
|
|
local MA_DIR="$DOCKER_DIR/mail-archiver"
|
|
|
|
if [ "$DRY_RUN" = true ]; then
|
|
echo "[DRY-RUN] Would create $MA_DIR (mailarchiver_database/)"
|
|
echo "[DRY-RUN] Would deploy s1t5/mailarchiver:latest + postgres:17-alpine"
|
|
echo "[DRY-RUN] Accessed via Caddy reverse proxy (no direct host port)"
|
|
echo "[DRY-RUN] Would generate DB and admin passwords"
|
|
return 0
|
|
fi
|
|
|
|
mkdir -p "$MA_DIR/mailarchiver_database"
|
|
ensure_docker_dir_ownership "$MA_DIR"
|
|
cd "$MA_DIR" || return 1
|
|
|
|
local DB_PASS ADMIN_PASS TZ_VAL
|
|
DB_PASS=$(generate_password 32)
|
|
ADMIN_PASS=$(generate_password 24)
|
|
TZ_VAL="${SITE_TZ:-$(cat /etc/timezone 2>/dev/null || echo UTC)}"
|
|
|
|
cat > docker-compose.yml << 'MA_COMPOSE'
|
|
name: mail-archiver
|
|
|
|
services:
|
|
mailarchiver-app:
|
|
image: s1t5/mailarchiver:latest
|
|
container_name: mailarchiver-app
|
|
hostname: mailarchiver-app
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
expose:
|
|
- "5000"
|
|
depends_on:
|
|
mailarchiver-db:
|
|
condition: service_healthy
|
|
networks:
|
|
- caddy_net
|
|
|
|
mailarchiver-db:
|
|
image: postgres:17-alpine
|
|
container_name: mailarchiver-db
|
|
hostname: mailarchiver-db
|
|
restart: unless-stopped
|
|
env_file: .env
|
|
expose:
|
|
- "5432"
|
|
volumes:
|
|
- ./mailarchiver_database:/var/lib/postgresql/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U mailuser -d MailArchiver"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 5
|
|
start_period: 30s
|
|
|
|
networks:
|
|
caddy_net:
|
|
external: true
|
|
name: ${CADDY_NET:-caddy_net}
|
|
MA_COMPOSE
|
|
|
|
cat > .env << MA_ENV
|
|
# ── General ───────────────────────────────────────────────────────────────────
|
|
TZ=$TZ_VAL
|
|
CADDY_NET=$SITE_CADDY_NET
|
|
|
|
# ── Database connection (app → postgres) ──────────────────────────────────────
|
|
ConnectionStrings__DefaultConnection=Host=mailarchiver-db;Database=MailArchiver;Username=mailuser;Password=$DB_PASS;
|
|
|
|
# ── Web authentication ────────────────────────────────────────────────────────
|
|
Authentication__Enabled=true
|
|
Authentication__Username=admin
|
|
Authentication__Password=$ADMIN_PASS
|
|
Authentication__SessionTimeoutMinutes=60
|
|
Authentication__CookieName=MailArchiverAuth
|
|
|
|
# ── Mail sync schedule ────────────────────────────────────────────────────────
|
|
MailSync__IntervalMinutes=15
|
|
MailSync__TimeoutMinutes=60
|
|
MailSync__ConnectionTimeoutSeconds=180
|
|
MailSync__CommandTimeoutSeconds=300
|
|
|
|
# ── Batch restore limits ──────────────────────────────────────────────────────
|
|
BatchRestore__AsyncThreshold=50
|
|
BatchRestore__MaxSyncEmails=150
|
|
BatchRestore__MaxAsyncEmails=50000
|
|
BatchRestore__SessionTimeoutMinutes=30
|
|
BatchRestore__DefaultBatchSize=50
|
|
|
|
# ── Postgres tuning ───────────────────────────────────────────────────────────
|
|
Npgsql__CommandTimeout=600
|
|
|
|
# ── Postgres container ────────────────────────────────────────────────────────
|
|
POSTGRES_DB=MailArchiver
|
|
POSTGRES_USER=mailuser
|
|
POSTGRES_PASSWORD=$DB_PASS
|
|
MA_ENV
|
|
|
|
chmod 600 .env
|
|
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$MA_DIR"
|
|
log_success "Mail Archiver configured at $MA_DIR"
|
|
|
|
configure_caddy_for_service "Mail Archiver" "mailarchiver-app:5000" "mail"
|
|
|
|
write_readme "$MA_DIR" << MD
|
|
# Mail Archiver
|
|
|
|
Self-hosted IMAP email archive and full-text search.
|
|
Add your IMAP mail accounts through the web UI — Mail Archiver will pull
|
|
and index all messages, then let you search the full archive.
|
|
|
|
## Access
|
|
- URL: via Caddy reverse proxy (no direct host port)
|
|
- Login: admin / (see .env Authentication__Password)
|
|
|
|
## Adding mail accounts
|
|
1. Open the web UI → Settings → Mail Accounts
|
|
2. Add IMAP server, username, and password
|
|
3. Mail Archiver syncs every \`MailSync__IntervalMinutes\` minutes (default: 15)
|
|
|
|
## Credentials
|
|
Stored in \`.env\` (chmod 600):
|
|
- Web admin password: \`Authentication__Password\`
|
|
- DB password: \`POSTGRES_PASSWORD\`
|
|
|
|
## Manage
|
|
\`\`\`bash
|
|
cd $MA_DIR
|
|
docker compose up -d # start
|
|
docker compose down # stop
|
|
docker compose logs -f # logs
|
|
docker compose pull && docker compose up -d # update
|
|
\`\`\`
|
|
MD
|
|
|
|
local START_MA=""
|
|
prompt_yn "Start Mail Archiver now? (y/n):" "y" START_MA
|
|
if [ "$START_MA" = "y" ] || [ "$START_MA" = "Y" ]; then
|
|
docker compose up -d \
|
|
&& log_success "Mail Archiver started" \
|
|
|| log_warning "Failed to start — check: docker compose logs"
|
|
fi
|
|
|
|
echo ""
|
|
echo " Admin login: admin / $(grep Authentication__Password .env | cut -d= -f2)"
|
|
echo " Add IMAP accounts via the web UI after starting."
|
|
echo ""
|
|
}
|