commit abd415fff0fbd3a0c2317cc6d6abd30bae10f997 Author: Amirhossein Khalili Date: Mon Mar 23 02:53:33 2026 +0800 initial commit diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..358f2dd --- /dev/null +++ b/.env.sample @@ -0,0 +1,54 @@ +# ========================================== +# Poste.io Mail Server Configuration +# ========================================== + +# Your mail server's Fully Qualified Domain Name (FQDN) +MAIL_HOSTNAME=mail.amiirkhl.ir + +# Server Timezone +TZ=Asia/Tehran + + +# ========================================== +# Performance & Feature Toggles +# ========================================== + +# Disable ClamAV Antivirus to save RAM. +# TRUE saves ~$1 \text{ GB}$ of RAM. FALSE provides better security. +DISABLE_CLAMAV=TRUE + +# Disable Rspamd (Anti-spam filter). +# Highly recommended to keep FALSE unless testing. +DISABLE_RSPAMD=FALSE + +# Disable the built-in Roundcube Webmail interface. +# TRUE disables it, FALSE enables it. +DISABLE_ROUNDCUBE=FALSE + + +# ========================================== +# SSL / HTTPS Configuration +# ========================================== + +# Controls Let's Encrypt and HTTP->HTTPS redirection. +# Since you are using custom SSL certificates manually, set this to OFF +# so Poste.io doesn't try to fetch its own certificates from Let's Encrypt. +HTTPS=OFF + +# Absolute paths to your custom SSL certificates on the host machine +# Docker will mount these directly into the container. +SSL_CERT_PATH=/path/to/your/fullchain.pem +SSL_KEY_PATH=/path/to/your/privatekey.pem + +# ========================================== +# Backup Configuration +# ========================================== + +# Enable automated backups (TRUE/FALSE) +ENABLE_BACKUPS=TRUE + +# Backup interval in cron format (e.g., "0 2 * * *" for daily at 2 AM) +BACKUP_CRON="0 2 * * *" + +# Number of days to keep old backups +BACKUP_RETENTION_DAYS=7 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8d31603 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Ignore the actual environment variables file +.env + +# Ignore the data directory which will contain emails, databases, and private SSL keys +/data/ + +# OS generated files +.DS_Store +Thumbs.db + +# Backup files +/backups/ +backup.log diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d03475 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# Poste.io Dockerized Mail Server + +Self-hosted, Git-managed mail server for your personal domain using [Poste.io](https://poste.io/). + +*Last Updated: 1405/01/02 (2026/03/22)* + +## Project Structure +```text +poste-deployment +├── .env.sample +├── .gitignore +├── docker-compose.yml +└── README.md +``` + +## Setup Instructions + +### 1. Clone & Configure +Clone this repository to your server: +```bash +git clone https://git.amiirkhl.ir/interanet/poste-deployment.git /opt/mailserver +cd /opt/mailserver +``` + +Create your environment file from the sample: +```bash +cp .env.sample .env +``` +Edit `.env` and ensure `MAIL_HOSTNAME` and `TZ` are correct. + +### 2. Custom SSL Configuration +Since Let's Encrypt is disabled (`HTTPS=OFF`), you must provide your own SSL certificates. This project maps your existing certificates directly into the container. + +1. Open your `.env` file. +2. Locate `SSL_CERT_PATH` and `SSL_KEY_PATH`. +3. Set their values to the **absolute paths** of your certificate files on the host server (e.g., `/etc/ssl/amiirkhl.ir/fullchain.pem`). + +*⚠️ **CRITICAL DOCKER WARNING**: The files specified in `SSL_CERT_PATH` and `SSL_KEY_PATH` **must** exist on your server before you run `docker compose up`. If Docker cannot find the files, it will mistakenly create empty directories with those names, which will crash the mail server.* + +### 3. Start the Server +Start the Docker container: +```bash +docker compose up -d +``` +Once running, navigate to `https://mail.amiirkhl.ir` to access the Admin GUI and set your master admin password. + +--- + +## DNS Configuration Guide + +To ensure your emails do not go to the spam folder, configure the following records in your DNS management panel (Cloudflare, ArvanCloud, etc.). + +*⚠️ **Important**: Ensure any Proxy/CDN settings (like Cloudflare's orange cloud) are turned **OFF** (DNS Only) for these records.* + +| Type | Name / Host | Value / Target | Priority | +| :---: | :--- | :--- | :---: | +| **A** | `mail` | `` | - | +| **MX** | `@` | `mail.amiirkhl.ir` | $10$ | +| **TXT** | `@` | `v=spf1 mx a:mail.amiirkhl.ir ~all` | - | +| **TXT** | `_dmarc` | `v=DMARC1; p=quarantine; rua=mailto:admin@amiirkhl.ir` | - | + +### DKIM Setup +DKIM adds a cryptographic signature to your emails. +1. Log into the Poste.io Admin Panel (`https://mail.amiirkhl.ir`). +2. Navigate to **Virtual domains** -> Click on `amiirkhl.ir`. +3. Locate the **DKIM key** section. +4. Click "Generate new key" (if not already generated). +5. Copy the provided TXT record and add it to your DNS panel. Usually, the Name is `s1._domainkey` and the Value is `v=DKIM1; k=rsa; p=...`. + +--- + +## Data Persistence & Backups +All user data, emails, databases, and configuration overrides are stored inside the `./data` folder. + +### Automated Backups +This project includes a script to automate backups of your `./data` directory based on your `.env` configuration. + +1. Ensure the backup variables are set in your `.env` file: + - `ENABLE_BACKUPS=TRUE` + - `BACKUP_CRON="0 2 * * *"` (Sets the schedule, e.g., daily at $2$ AM) + - `BACKUP_RETENTION_DAYS=7` (Deletes backups older than $7$ days) + +2. Make the setup script executable and run it: + ```bash + chmod +x setup_backup.sh + ./setup_backup.sh + ``` + +The script will automatically register a cron job on your host machine. Backups will be securely compressed as `.tar.gz` files and stored in the newly created `./backups` directory. Old backups are automatically pruned based on your retention settings. + +### Manual Backup +If you prefer to trigger a backup manually at any time without using the script, simply run: +```bash +tar -czvf mail_backup_$(date +%F).tar.gz ./data/ +``` diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..b72b775 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,31 @@ +services: + mailserver: + image: analogic/poste.io:latest + hostname: ${MAIL_HOSTNAME} + restart: always + ports: + - "25:25" + - "80:80" + - "443:443" + - "110:110" + - "143:143" + - "465:465" + - "587:587" + - "993:993" + - "995:995" + environment: + - TZ=${TZ} + - DISABLE_CLAMAV=${DISABLE_CLAMAV} + - DISABLE_RSPAMD=${DISABLE_RSPAMD} + - DISABLE_ROUNDCUBE=${DISABLE_ROUNDCUBE} + - HTTPS=${HTTPS} + - ${SSL_CERT_PATH}:/data/ssl/server.crt:ro + - ${SSL_KEY_PATH}:/data/ssl/server.key:ro + volumes: + - ./data:/data + +logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" diff --git a/setup_backup.sh b/setup_backup.sh new file mode 100644 index 0000000..3e4ad65 --- /dev/null +++ b/setup_backup.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# Load environment variables +if [ -f .env ]; then + export $(grep -v '^#' .env | xargs) +else + echo "Error: .env file not found." + exit 1 +fi + +if [ "$ENABLE_BACKUPS" != "TRUE" ]; then + echo "Backups are disabled in .env. Exiting." + exit 0 +fi + +PROJECT_DIR=$(pwd) +BACKUP_DIR="${PROJECT_DIR}/backups" +BACKUP_SCRIPT="${PROJECT_DIR}/run_backup.sh" + +# Create backups directory +mkdir -p "$BACKUP_DIR" + +# Create the actual backup script that cron will run +cat < "$BACKUP_SCRIPT" +#!/bin/bash +# Auto-generated backup script +mkdir -p "$BACKUP_DIR" +cd "$PROJECT_DIR" + +# Create new backup +FILENAME="mail_backup_\$(date +%F_%H-%M-%S).tar.gz" +tar -czvf "$BACKUP_DIR/\$FILENAME" ./data/ > /dev/null 2>&1 + +# Delete old backups based on retention days +find "$BACKUP_DIR" -type f -name "mail_backup_*.tar.gz" -mtime +$BACKUP_RETENTION_DAYS -exec rm {} \; +EOF + +chmod +x "$BACKUP_SCRIPT" + +# Remove existing cron job for this backup script to avoid duplicates +crontab -l | grep -v "$BACKUP_SCRIPT" | crontab - + +# Add new cron job +(crontab -l 2>/dev/null; echo "$BACKUP_CRON $BACKUP_SCRIPT >> $PROJECT_DIR/backup.log 2>&1") | crontab - + +echo "Backup automation configured successfully!" +echo "Schedule: $BACKUP_CRON" +echo "Retention: $BACKUP_RETENTION_DAYS days" +echo "Backups will be saved to: $BACKUP_DIR"