├── .github └── workflows │ ├── build-docker-image.yml │ └── check-docker-image-update.yml ├── .gitignore ├── Dockerfile.3.5 ├── Dockerfile.3.6 ├── Dockerfile.3.7 ├── Dockerfile.3.8 ├── Dockerfile.latest ├── README.md ├── conf ├── local.d │ ├── README.md │ ├── actions.conf │ ├── antivirus.conf │ ├── classifier-bayes.conf │ ├── dcc.conf │ ├── external_services.conf │ ├── fuzzy_check.conf │ ├── greylist.conf │ ├── history_redis.conf │ ├── logging.inc │ ├── maps.d │ │ └── spamtrap.map │ ├── metrics.conf │ ├── mime_types.conf │ ├── mime_types_group.conf │ ├── multimap.conf │ ├── mx_check.conf │ ├── neural.conf │ ├── neural_group.conf │ ├── once_received.conf │ ├── phishing.conf │ ├── policies_group.conf │ ├── ratelimit.conf │ ├── rbl_group.conf │ ├── redis.conf │ ├── replies.conf │ ├── spamtrap.conf │ ├── spf.conf │ ├── statistics_group.conf │ ├── url_reputation.conf │ ├── url_tags.conf │ ├── whitelist.conf │ ├── worker-controller-readme.txt │ ├── worker-fuzzy.inc │ └── worker-normal.inc ├── plugins.d │ ├── __razor.lua__ │ └── pyzor.lua └── rspamd.conf.local ├── docker-compose.yml ├── entrypoint.sh └── rspamd-logo.png /.github/workflows/build-docker-image.yml: -------------------------------------------------------------------------------- 1 | name: Build and Scan Docker Image 2 | 3 | on: 4 | push: 5 | paths: 6 | - 'Dockerfile.*' 7 | - 'entrypoint.sh' 8 | - 'unbound.conf' 9 | pull_request: 10 | paths: 11 | - 'Dockerfile.latest' 12 | - 'entrypoint.sh' 13 | - 'unbound.conf' 14 | workflow_dispatch: # Permette di avviare il workflow manualmente dalla UI di GitHub 15 | inputs: 16 | versions_to_build: 17 | description: 'Inserisci una versione specifica da compilare (es. 22.04 o latest o più elementi separati da virgola). Lascia vuoto per compilare tutte le versioni.' 18 | required: false 19 | type: string 20 | default: '' # Valore di default vuoto per compilare tutte le versioni 21 | workflow_call: # Permette di riutilizzare il workflow da un altro repo 22 | inputs: 23 | dockertag: 24 | description: 'Tag for the image' 25 | required: false 26 | type: string 27 | default: "latest" 28 | 29 | jobs: 30 | # Job per generare dinamicamente la matrice 31 | generate_matrix: 32 | runs-on: ubuntu-latest 33 | outputs: 34 | versions: ${{ steps.set_versions.outputs.versions }} 35 | steps: 36 | - name: Set Versions for Matrix 37 | id: set_versions 38 | run: | 39 | set -euo pipefail # Fail immediately if any command fails or variable is unset 40 | 41 | # Check if jq is available (it should be on ubuntu-latest) 42 | if ! command -v jq &> /dev/null 43 | then 44 | echo "Error: jq is not installed. It is required for this step." 45 | exit 1 46 | fi 47 | 48 | INPUT_VERSIONS=$(printf "%s" "${{ inputs.versions_to_build }}" | tr -d '\n' | xargs) 49 | 50 | # Lista completa di tutte le versioni disponibili 51 | ALL_VERSIONS="latest,3.8,3.7,3.6,3.5" 52 | 53 | if [ -z "$INPUT_VERSIONS" ]; then 54 | SELECTED_VERSIONS="$ALL_VERSIONS" 55 | echo "Building all versions: $SELECTED_VERSIONS" 56 | else 57 | SELECTED_VERSIONS="$INPUT_VERSIONS" 58 | echo "Building selected versions: $SELECTED_VERSIONS" 59 | fi 60 | 61 | # Converte la stringa separata da virgole in un array JSON 62 | # e imposta l'output 'versions'. 63 | # `map(select(length > 0))` filtra gli elementi vuoti (es. se la stringa fosse "v1,,v2") 64 | # `-c` per output compatto, senza nuove righe. 65 | JSON_VERSIONS=$(jq -c -R -s 'split(",") | map(select(length > 0) | gsub("\\n"; ""))' <<< "$SELECTED_VERSIONS") 66 | 67 | # Scrive la variabile di output nel file $GITHUB_OUTPUT usando printf per precisione 68 | printf "versions=%s\n" "$JSON_VERSIONS" >> "$GITHUB_OUTPUT" 69 | shell: bash 70 | 71 | build-and-push: 72 | secrets: inherit 73 | needs: generate_matrix 74 | strategy: 75 | matrix: 76 | #version: [latest, 24.04, 22.04, 20.04, 18.04] 77 | version: ${{ fromJSON(needs.generate_matrix.outputs.versions) }} 78 | max-parallel: 1 79 | # non posso parallellizzare il processo perché l'upload delle immagini va in errore con "permission denied" 80 | 81 | uses: Neomediatech/gh-workflows/.github/workflows/build-and-push-docker-image.yml@main 82 | with: 83 | dockerfile: "Dockerfile.${{ matrix.version }}" 84 | dockerdir: "." 85 | dockertag: ${{ matrix.version }} 86 | 87 | scan-docker-image: 88 | secrets: inherit 89 | strategy: 90 | matrix: 91 | #version: [latest, 24.04, 22.04, 20.04, 18.04] 92 | version: ${{ fromJSON(needs.generate_matrix.outputs.versions) }} 93 | needs: [generate_matrix, build-and-push] 94 | uses: Neomediatech/gh-workflows/.github/workflows/scan-docker-image.yml@main 95 | with: 96 | dockertag: ${{ matrix.version }} 97 | 98 | push-report-to-repo: 99 | strategy: 100 | matrix: 101 | #version: [latest, 24.04, 22.04, 20.04, 18.04] 102 | version: ${{ fromJSON(needs.generate_matrix.outputs.versions) }} 103 | max-parallel: 1 104 | needs: [generate_matrix, scan-docker-image] 105 | secrets: inherit 106 | uses: Neomediatech/gh-workflows/.github/workflows/copy-file-to-another-repo.yml@main 107 | with: 108 | file_id: ${{ needs.scan-docker-image.outputs.uploaded-file-id }} 109 | filename: ${{ needs.scan-docker-image.outputs.file_to_copy_output }} 110 | dockertag: ${{ matrix.version }} 111 | 112 | -------------------------------------------------------------------------------- /.github/workflows/check-docker-image-update.yml: -------------------------------------------------------------------------------- 1 | name: Check Base Image Updates and Rebuild 2 | 3 | on: 4 | #schedule: 5 | # Esegui ogni giorno alle 04:00 UTC per controllare gli aggiornamenti. 6 | # - cron: '0 4 * * *' 7 | workflow_dispatch: 8 | 9 | jobs: 10 | get-infos: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | packages: write 15 | outputs: 16 | repo_lower_output: ${{ steps.get_lowercase_repo.outputs.repo_lower }} 17 | base_image_output: ${{ steps.base_image_info.outputs.base_image }} # Assicurati di esporre anche questo 18 | 19 | strategy: 20 | matrix: 21 | version: [latest] 22 | max-parallel: 1 23 | 24 | steps: 25 | - name: Checkout code 26 | uses: actions/checkout@v4 27 | 28 | - name: Determine Base Image and Dockerfile Info 29 | id: base_image_info 30 | run: | 31 | DOCKERFILE_NAME="Dockerfile.${{ matrix.version }}" 32 | 33 | # Verifica che il Dockerfile esista 34 | if [ ! -f "${DOCKERFILE_NAME}" ]; then 35 | echo "Error: Dockerfile not found at ${DOCKERFILE_NAME}" 36 | exit 1 37 | fi 38 | 39 | # Estrae la prima riga che inizia con "FROM". 40 | BASE_IMAGE_LINE=$(cat "${DOCKERFILE_NAME}" | grep -m 1 "^FROM") 41 | 42 | # Verifica che ci sia una riga FROM 43 | if [ -z "${BASE_IMAGE_LINE}" ]; then 44 | echo "Error: No FROM instruction found in ${DOCKERFILE_NAME}" 45 | exit 1 46 | fi 47 | 48 | # Estrae solo il nome dell'immagine base (es. "ubuntu:24.04" o "node:lts-alpine"). 49 | BASE_IMAGE=$(echo "${BASE_IMAGE_LINE}" | sed -E 's/FROM ([^ ]+)( AS .*)?/\1/') 50 | 51 | echo "Determined base image for ${DOCKERFILE_NAME}: ${BASE_IMAGE}" 52 | echo "base_image=${BASE_IMAGE}" >> $GITHUB_OUTPUT 53 | echo "dockerfile_name=${DOCKERFILE_NAME}" >> $GITHUB_OUTPUT 54 | echo "docker_full_tag=${{ matrix.version }}" >> $GITHUB_OUTPUT # Tag completo per l'immagine finale 55 | 56 | - name: Log in to GitHub Container Registry 57 | uses: docker/login-action@v3 58 | with: 59 | registry: ghcr.io 60 | username: ${{ github.actor }} 61 | password: ${{ secrets.GITHUB_TOKEN }} 62 | # Esegui il login solo se l'immagine base è stata determinata (e quindi il job non è stato saltato). 63 | if: ${{ steps.base_image_info.outputs.base_image != '' }} 64 | 65 | - name: Get Lowercase Repository Name 66 | id: get_lowercase_repo # Assegniamo un ID a questo step per poterne usare l'output 67 | run: | 68 | # Ottiene il nome del repository e lo converte in minuscolo 69 | LOWER_REPO=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]') 70 | echo "Lowercased repository name: $LOWER_REPO" 71 | # Esporta il valore in minuscolo come output dello step 72 | echo "repo_lower=$LOWER_REPO" >> $GITHUB_OUTPUT 73 | 74 | - name: Log in to GitHub Container Registry 75 | uses: docker/login-action@v3 76 | with: 77 | registry: ghcr.io 78 | username: ${{ github.actor }} 79 | password: ${{ secrets.GITHUB_TOKEN }} 80 | 81 | check-update: 82 | secrets: inherit 83 | strategy: 84 | matrix: 85 | version: [latest] 86 | max-parallel: 1 87 | uses: Neomediatech/gh-workflows/.github/workflows/check-docker-image-update.yml@main 88 | needs: get-infos 89 | with: 90 | image_repo: ghcr.io/${{ needs.get-infos.outputs.repo_lower_output }} 91 | dockertag: ${{ matrix.version }} 92 | base_image: ${{ needs.get-infos.outputs.base_image_output }} 93 | if: ${{ needs.get-infos.outputs.base_image_output != '' }} 94 | 95 | rebuild: 96 | secrets: inherit 97 | strategy: 98 | matrix: 99 | version: [latest] 100 | max-parallel: 1 101 | uses: ./.github/workflows/build-docker-image.yml 102 | needs: check-update 103 | with: 104 | dockertag: ${{ matrix.version }} 105 | if: ${{ needs.check-update.outputs.needs-updating == 'true' }} 106 | 107 | no-need-message: 108 | runs-on: ubuntu-latest 109 | needs: rebuild 110 | steps: 111 | - name: No update needed 112 | # Esegui questo step se l'immagine base non è stata aggiornata. 113 | if: steps.check.outputs.needs-updating == 'false' && steps.base_image_info.outputs.base_image != '' 114 | run: | 115 | echo "L'immagine base per la versione ${{ matrix.version }} non è stata aggiornata, nessuna azione necessaria." 116 | #echo "L'immagine base per la versione ${{ matrix.version }}-${{ matrix.type }} non è stata aggiornata, nessuna azione necessaria." 117 | 118 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | trigger-build.sh 2 | run.sh 3 | vars 4 | tests/ 5 | build.sh 6 | 7 | -------------------------------------------------------------------------------- /Dockerfile.3.5: -------------------------------------------------------------------------------- 1 | FROM neomediatech/ubuntu-base:20.04 2 | 3 | ENV RSPAMD_VERSION=3.5-2~0c671194e~focal \ 4 | SERVICE=rspamd 5 | 6 | LABEL maintainer="docker-dario@neomediatech.it" \ 7 | org.label-schema.version=$RSPAMD_VERSION \ 8 | org.label-schema.vcs-type=Git \ 9 | org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ 10 | org.label-schema.maintainer=Neomediatech 11 | 12 | RUN apt-get update && apt-get -y dist-upgrade && \ 13 | apt-get install -y --no-install-recommends \ 14 | ca-certificates lsb-release wget gnupg && \ 15 | CODENAME=`lsb_release -c -s` && \ 16 | wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add - && \ 17 | echo "deb [arch=amd64] http://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list && \ 18 | echo "deb-src [arch=amd64] http://rspamd.com/apt-stable/ $CODENAME main" >> /etc/apt/sources.list.d/rspamd.list && \ 19 | apt-get update && \ 20 | apt-get --no-install-recommends install -y rspamd && \ 21 | rm -rf /var/lib/apt/lists/* && \ 22 | echo 'pidfile = false;' > /etc/rspamd/override.d/options.inc && \ 23 | mkdir -p /srv/scripts && \ 24 | wget -O /srv/scripts/logrotate.sh https://raw.githubusercontent.com/Neomediatech/assets/main/scripts/logrotate.sh && \ 25 | chmod +x /srv/scripts/logrotate.sh 26 | 27 | COPY conf/ /etc/rspamd 28 | COPY entrypoint.sh /entrypoint.sh 29 | RUN chmod +x /entrypoint.sh 30 | 31 | HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=20 CMD rspamadm control stat |grep uptime|head -1 || ( echo "no uptime, no party\!" && exit 1 ) 32 | 33 | ENTRYPOINT ["/entrypoint.sh"] 34 | CMD [ "/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd" ] 35 | -------------------------------------------------------------------------------- /Dockerfile.3.6: -------------------------------------------------------------------------------- 1 | FROM neomediatech/ubuntu-base:22.04 2 | 3 | ENV APP_VERSION=3.6 \ 4 | SERVICE=rspamd 5 | 6 | LABEL maintainer="docker-dario@neomediatech.it" \ 7 | org.label-schema.version=$APP_VERSION \ 8 | org.label-schema.vcs-type=Git \ 9 | org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ 10 | org.label-schema.maintainer=Neomediatech 11 | 12 | RUN apt-get update && apt-get -y dist-upgrade && \ 13 | apt-get install -y --no-install-recommends \ 14 | ca-certificates lsb-release wget gnupg && \ 15 | apt-get clean && \ 16 | rm -rf /var/lib/apt/lists/* 17 | 18 | SHELL ["/bin/bash", "-c"] 19 | RUN set -x \ 20 | # gpg: key FFA232EDBF21E25E: public key "Rspamd Nightly Builds (Rspamd Nightly Builds) " imported 21 | && key='3FA347D5E599BE4595CA2576FFA232EDBF21E25E' \ 22 | && export GNUPGHOME="$(mktemp -d)" \ 23 | && gpg --import <<<$'\ 24 | -----BEGIN PGP PUBLIC KEY BLOCK----- \n\ 25 | \n\ 26 | mQINBFW3VB8BEADAV1lBy8DPcSEBSLYVKgwsBx/dRmgenKeliMpiZyNYJJmF6tSV \n\ 27 | s3v5DtDIUESgI2mBKNeptdneri3CDJScI/LgPLKqemrLBkAMfe+f57JgppY5ti4H \n\ 28 | xo+VZdbF9bhCAwYwJnqnyuLjYSUu6nCuW4uPDoqBHXynwsIWr1O3fREpY+vgIgaT \n\ 29 | Oqm3ncssqxSicymd6k0yuo55xuUvrc4Yu4IEnhFVRU53e0E3zmHg/7ONI99YtBan \n\ 30 | 7G/w2IfA1bfRDYZ2Avau+JqGcEl8vy+eLmYayKirdsMPN8Tx6RFOstDf1CnjW/bj \n\ 31 | IX7SDOklIGJjJwcWW/iY+1P9SfNNqSDgXavJj2wmLMlUhgjyJFTXfdDRjmN0PFxo \n\ 32 | f6OQu5xok1WHfKFJL+hLGknjHdXLmGd5MSuFlutdVHJQrieknjBea9xCiEsrfe8V \n\ 33 | zyNqGhzgIYjOi/bO7jGpY/WiFHvM9XtBVp862tqM1S1WbAWW5u+es6NK4q9Cv0DR \n\ 34 | tIalss+5gFhdsIFGFYQWfY7CrjOIC+C0+c5IGaBkHte35hCCvDpOO909xxVqUZYe \n\ 35 | 9Pl8zYgPDe1H4arMO+p6rSvVntvIWOqLqkuWYSiOY4TGADJTkeZRbopZhvqs/9mc \n\ 36 | 847fVMbOwKfkbeuGiHhUK0QFewXSu+cXJyGtyu3RgokBWr2yyzJFXIvJbQARAQAB \n\ 37 | tEZSc3BhbWQgTmlnaHRseSBCdWlsZHMgKFJzcGFtZCBOaWdodGx5IEJ1aWxkcykg \n\ 38 | PHZzZXZvbG9kQGhpZ2hzZWN1cmUucnU+iQI4BBMBAgAiBQJVt1QfAhsDBgsJCAcD \n\ 39 | AgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD/ojLtvyHiXucND/4ja0t+4RMiD0c0z3xD \n\ 40 | Vp0Ysq7kZvzlteUrw98f1BMYbmSTJ+43JVZV67GJ8fV2d9/atIlyLce8Gn9hYmF7 \n\ 41 | C5nPpCCOlNejkwkc9MhZgoM0z7sTNZwKLZ4fSnxHD10Z923G+IRQYeXswM7hE/T5 \n\ 42 | 8NgANOWBFs9BxIEIT6IfRNHF23SCmCeNFNmUen6uXLznjRzYbMmwP7u2BopfJcpN \n\ 43 | ajnm66IypQDsUqVwBRnm9o9GAWUPbp4ahhf1vYu04T1vD7n4qhrLdhHmEJpukEhD \n\ 44 | q613Wl/k0g0O8SahfSAaM1x5zLOJ0sMacyxCktQKXypAhkhhJc4J1KLbnNUsxZdk \n\ 45 | Gn4wLZuhfIuzh2KfKBdwoL3zRq7kjgumJo7AQhEIIDGKutl6sZnbRHjBr4qBb1NJ \n\ 46 | /7GC7UiZhIesdO6HdqrriNF0l8dRVIaHXGKF0PQWWG+J+147oQM+SJmm4W4oONSx \n\ 47 | YCjyTllxwh/54fhu81jhSyBgbKAmV1gYLIPvAUgPkguAb5JWcvZOeXytHWZYLK9T \n\ 48 | 8rW5R0bviiouHHRyQYu0AX+wiSyAfoVnTVyad6xTWUT3aQ8jeL0I3uy323Mrq56U \n\ 49 | 7Yo0NFwKPF9z5kbuQje3daudQQymkhOfNcQm3dOaaWKGp5KPRi3OtKYMu+5Aphor \n\ 50 | lwJWDec6PUe835YwqrARXtPaNA== \n\ 51 | =4Cm3 \n\ 52 | -----END PGP PUBLIC KEY BLOCK-----' \ 53 | && gpg --keyserver hkps://keys.openpgp.org --recv-keys "$key" \ 54 | && gpg --export "$key" > /etc/apt/trusted.gpg.d/rspamd.gpg \ 55 | && rm -rf "$GNUPGHOME" \ 56 | && apt-key list > /dev/null 57 | 58 | RUN CODENAME=`lsb_release -c -s` && \ 59 | echo "deb [signed-by=/etc/apt/trusted.gpg.d/rspamd.gpg] https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list && \ 60 | apt-get update && \ 61 | apt-get --no-install-recommends install -y rspamd && \ 62 | apt-get clean && \ 63 | rm -rf /var/lib/apt/lists/* && \ 64 | echo 'pidfile = false;' > /etc/rspamd/override.d/options.inc && \ 65 | mkdir -p /srv/scripts && \ 66 | wget -O /srv/scripts/logrotate.sh https://raw.githubusercontent.com/Neomediatech/assets/main/scripts/logrotate.sh && \ 67 | chmod +x /srv/scripts/logrotate.sh 68 | 69 | COPY conf/ /etc/rspamd 70 | COPY entrypoint.sh /entrypoint.sh 71 | RUN chmod +x /entrypoint.sh 72 | 73 | HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=20 CMD rspamadm control stat |grep uptime|head -1 || ( echo "no uptime, no party\!" && exit 1 ) 74 | 75 | ENTRYPOINT ["/entrypoint.sh"] 76 | CMD [ "/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd" ] 77 | 78 | -------------------------------------------------------------------------------- /Dockerfile.3.7: -------------------------------------------------------------------------------- 1 | FROM neomediatech/ubuntu-base:22.04 2 | 3 | ENV APP_VERSION=3.7 \ 4 | SERVICE=rspamd 5 | 6 | LABEL maintainer="docker-dario@neomediatech.it" \ 7 | org.label-schema.version=$APP_VERSION \ 8 | org.label-schema.vcs-type=Git \ 9 | org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ 10 | org.label-schema.maintainer=Neomediatech 11 | 12 | RUN apt-get update && apt-get -y dist-upgrade && \ 13 | apt-get install -y --no-install-recommends \ 14 | ca-certificates lsb-release wget gnupg && \ 15 | apt-get clean && \ 16 | rm -rf /var/lib/apt/lists/* 17 | 18 | SHELL ["/bin/bash", "-c"] 19 | RUN set -x \ 20 | # gpg: key FFA232EDBF21E25E: public key "Rspamd Nightly Builds (Rspamd Nightly Builds) " imported 21 | && key='3FA347D5E599BE4595CA2576FFA232EDBF21E25E' \ 22 | && export GNUPGHOME="$(mktemp -d)" \ 23 | && gpg --import <<<$'\ 24 | -----BEGIN PGP PUBLIC KEY BLOCK----- \n\ 25 | \n\ 26 | mQINBFW3VB8BEADAV1lBy8DPcSEBSLYVKgwsBx/dRmgenKeliMpiZyNYJJmF6tSV \n\ 27 | s3v5DtDIUESgI2mBKNeptdneri3CDJScI/LgPLKqemrLBkAMfe+f57JgppY5ti4H \n\ 28 | xo+VZdbF9bhCAwYwJnqnyuLjYSUu6nCuW4uPDoqBHXynwsIWr1O3fREpY+vgIgaT \n\ 29 | Oqm3ncssqxSicymd6k0yuo55xuUvrc4Yu4IEnhFVRU53e0E3zmHg/7ONI99YtBan \n\ 30 | 7G/w2IfA1bfRDYZ2Avau+JqGcEl8vy+eLmYayKirdsMPN8Tx6RFOstDf1CnjW/bj \n\ 31 | IX7SDOklIGJjJwcWW/iY+1P9SfNNqSDgXavJj2wmLMlUhgjyJFTXfdDRjmN0PFxo \n\ 32 | f6OQu5xok1WHfKFJL+hLGknjHdXLmGd5MSuFlutdVHJQrieknjBea9xCiEsrfe8V \n\ 33 | zyNqGhzgIYjOi/bO7jGpY/WiFHvM9XtBVp862tqM1S1WbAWW5u+es6NK4q9Cv0DR \n\ 34 | tIalss+5gFhdsIFGFYQWfY7CrjOIC+C0+c5IGaBkHte35hCCvDpOO909xxVqUZYe \n\ 35 | 9Pl8zYgPDe1H4arMO+p6rSvVntvIWOqLqkuWYSiOY4TGADJTkeZRbopZhvqs/9mc \n\ 36 | 847fVMbOwKfkbeuGiHhUK0QFewXSu+cXJyGtyu3RgokBWr2yyzJFXIvJbQARAQAB \n\ 37 | tEZSc3BhbWQgTmlnaHRseSBCdWlsZHMgKFJzcGFtZCBOaWdodGx5IEJ1aWxkcykg \n\ 38 | PHZzZXZvbG9kQGhpZ2hzZWN1cmUucnU+iQI4BBMBAgAiBQJVt1QfAhsDBgsJCAcD \n\ 39 | AgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD/ojLtvyHiXucND/4ja0t+4RMiD0c0z3xD \n\ 40 | Vp0Ysq7kZvzlteUrw98f1BMYbmSTJ+43JVZV67GJ8fV2d9/atIlyLce8Gn9hYmF7 \n\ 41 | C5nPpCCOlNejkwkc9MhZgoM0z7sTNZwKLZ4fSnxHD10Z923G+IRQYeXswM7hE/T5 \n\ 42 | 8NgANOWBFs9BxIEIT6IfRNHF23SCmCeNFNmUen6uXLznjRzYbMmwP7u2BopfJcpN \n\ 43 | ajnm66IypQDsUqVwBRnm9o9GAWUPbp4ahhf1vYu04T1vD7n4qhrLdhHmEJpukEhD \n\ 44 | q613Wl/k0g0O8SahfSAaM1x5zLOJ0sMacyxCktQKXypAhkhhJc4J1KLbnNUsxZdk \n\ 45 | Gn4wLZuhfIuzh2KfKBdwoL3zRq7kjgumJo7AQhEIIDGKutl6sZnbRHjBr4qBb1NJ \n\ 46 | /7GC7UiZhIesdO6HdqrriNF0l8dRVIaHXGKF0PQWWG+J+147oQM+SJmm4W4oONSx \n\ 47 | YCjyTllxwh/54fhu81jhSyBgbKAmV1gYLIPvAUgPkguAb5JWcvZOeXytHWZYLK9T \n\ 48 | 8rW5R0bviiouHHRyQYu0AX+wiSyAfoVnTVyad6xTWUT3aQ8jeL0I3uy323Mrq56U \n\ 49 | 7Yo0NFwKPF9z5kbuQje3daudQQymkhOfNcQm3dOaaWKGp5KPRi3OtKYMu+5Aphor \n\ 50 | lwJWDec6PUe835YwqrARXtPaNA== \n\ 51 | =4Cm3 \n\ 52 | -----END PGP PUBLIC KEY BLOCK-----' \ 53 | && gpg --keyserver hkps://keys.openpgp.org --recv-keys "$key" \ 54 | && gpg --export "$key" > /etc/apt/trusted.gpg.d/rspamd.gpg \ 55 | && rm -rf "$GNUPGHOME" \ 56 | && apt-key list > /dev/null 57 | 58 | RUN CODENAME=`lsb_release -c -s` && \ 59 | echo "deb [signed-by=/etc/apt/trusted.gpg.d/rspamd.gpg] https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list && \ 60 | apt-get update && \ 61 | apt-get --no-install-recommends install -y rspamd && \ 62 | apt-get clean && \ 63 | rm -rf /var/lib/apt/lists/* && \ 64 | echo 'pidfile = false;' > /etc/rspamd/override.d/options.inc && \ 65 | mkdir -p /srv/scripts && \ 66 | wget -O /srv/scripts/logrotate.sh https://raw.githubusercontent.com/Neomediatech/assets/main/scripts/logrotate.sh && \ 67 | chmod +x /srv/scripts/logrotate.sh 68 | 69 | COPY conf/ /etc/rspamd 70 | COPY entrypoint.sh /entrypoint.sh 71 | RUN chmod +x /entrypoint.sh 72 | 73 | HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=20 CMD rspamadm control stat |grep uptime|head -1 || ( echo "no uptime, no party\!" && exit 1 ) 74 | 75 | ENTRYPOINT ["/entrypoint.sh"] 76 | CMD [ "/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd" ] 77 | 78 | -------------------------------------------------------------------------------- /Dockerfile.3.8: -------------------------------------------------------------------------------- 1 | FROM neomediatech/ubuntu-base:22.04 2 | 3 | ENV APP_VERSION=3.8 \ 4 | SERVICE=rspamd 5 | 6 | LABEL maintainer="docker-dario@neomediatech.it" \ 7 | org.label-schema.version=$APP_VERSION \ 8 | org.label-schema.vcs-type=Git \ 9 | org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ 10 | org.label-schema.maintainer=Neomediatech 11 | 12 | RUN apt-get update && apt-get -y dist-upgrade && \ 13 | apt-get install -y --no-install-recommends \ 14 | ca-certificates lsb-release wget gnupg && \ 15 | apt-get clean && \ 16 | rm -rf /var/lib/apt/lists/* 17 | 18 | SHELL ["/bin/bash", "-c"] 19 | RUN set -x \ 20 | # gpg: key FFA232EDBF21E25E: public key "Rspamd Nightly Builds (Rspamd Nightly Builds) " imported 21 | && key='3FA347D5E599BE4595CA2576FFA232EDBF21E25E' \ 22 | && export GNUPGHOME="$(mktemp -d)" \ 23 | && gpg --import <<<$'\ 24 | -----BEGIN PGP PUBLIC KEY BLOCK----- \n\ 25 | \n\ 26 | mQINBFW3VB8BEADAV1lBy8DPcSEBSLYVKgwsBx/dRmgenKeliMpiZyNYJJmF6tSV \n\ 27 | s3v5DtDIUESgI2mBKNeptdneri3CDJScI/LgPLKqemrLBkAMfe+f57JgppY5ti4H \n\ 28 | xo+VZdbF9bhCAwYwJnqnyuLjYSUu6nCuW4uPDoqBHXynwsIWr1O3fREpY+vgIgaT \n\ 29 | Oqm3ncssqxSicymd6k0yuo55xuUvrc4Yu4IEnhFVRU53e0E3zmHg/7ONI99YtBan \n\ 30 | 7G/w2IfA1bfRDYZ2Avau+JqGcEl8vy+eLmYayKirdsMPN8Tx6RFOstDf1CnjW/bj \n\ 31 | IX7SDOklIGJjJwcWW/iY+1P9SfNNqSDgXavJj2wmLMlUhgjyJFTXfdDRjmN0PFxo \n\ 32 | f6OQu5xok1WHfKFJL+hLGknjHdXLmGd5MSuFlutdVHJQrieknjBea9xCiEsrfe8V \n\ 33 | zyNqGhzgIYjOi/bO7jGpY/WiFHvM9XtBVp862tqM1S1WbAWW5u+es6NK4q9Cv0DR \n\ 34 | tIalss+5gFhdsIFGFYQWfY7CrjOIC+C0+c5IGaBkHte35hCCvDpOO909xxVqUZYe \n\ 35 | 9Pl8zYgPDe1H4arMO+p6rSvVntvIWOqLqkuWYSiOY4TGADJTkeZRbopZhvqs/9mc \n\ 36 | 847fVMbOwKfkbeuGiHhUK0QFewXSu+cXJyGtyu3RgokBWr2yyzJFXIvJbQARAQAB \n\ 37 | tEZSc3BhbWQgTmlnaHRseSBCdWlsZHMgKFJzcGFtZCBOaWdodGx5IEJ1aWxkcykg \n\ 38 | PHZzZXZvbG9kQGhpZ2hzZWN1cmUucnU+iQI4BBMBAgAiBQJVt1QfAhsDBgsJCAcD \n\ 39 | AgYVCAIJCgsEFgIDAQIeAQIXgAAKCRD/ojLtvyHiXucND/4ja0t+4RMiD0c0z3xD \n\ 40 | Vp0Ysq7kZvzlteUrw98f1BMYbmSTJ+43JVZV67GJ8fV2d9/atIlyLce8Gn9hYmF7 \n\ 41 | C5nPpCCOlNejkwkc9MhZgoM0z7sTNZwKLZ4fSnxHD10Z923G+IRQYeXswM7hE/T5 \n\ 42 | 8NgANOWBFs9BxIEIT6IfRNHF23SCmCeNFNmUen6uXLznjRzYbMmwP7u2BopfJcpN \n\ 43 | ajnm66IypQDsUqVwBRnm9o9GAWUPbp4ahhf1vYu04T1vD7n4qhrLdhHmEJpukEhD \n\ 44 | q613Wl/k0g0O8SahfSAaM1x5zLOJ0sMacyxCktQKXypAhkhhJc4J1KLbnNUsxZdk \n\ 45 | Gn4wLZuhfIuzh2KfKBdwoL3zRq7kjgumJo7AQhEIIDGKutl6sZnbRHjBr4qBb1NJ \n\ 46 | /7GC7UiZhIesdO6HdqrriNF0l8dRVIaHXGKF0PQWWG+J+147oQM+SJmm4W4oONSx \n\ 47 | YCjyTllxwh/54fhu81jhSyBgbKAmV1gYLIPvAUgPkguAb5JWcvZOeXytHWZYLK9T \n\ 48 | 8rW5R0bviiouHHRyQYu0AX+wiSyAfoVnTVyad6xTWUT3aQ8jeL0I3uy323Mrq56U \n\ 49 | 7Yo0NFwKPF9z5kbuQje3daudQQymkhOfNcQm3dOaaWKGp5KPRi3OtKYMu+5Aphor \n\ 50 | lwJWDec6PUe835YwqrARXtPaNA== \n\ 51 | =4Cm3 \n\ 52 | -----END PGP PUBLIC KEY BLOCK-----' \ 53 | && gpg --keyserver hkps://keys.openpgp.org --recv-keys "$key" \ 54 | && gpg --export "$key" > /etc/apt/trusted.gpg.d/rspamd.gpg \ 55 | && rm -rf "$GNUPGHOME" \ 56 | && apt-key list > /dev/null 57 | 58 | RUN CODENAME=`lsb_release -c -s` && \ 59 | echo "deb [signed-by=/etc/apt/trusted.gpg.d/rspamd.gpg] https://rspamd.com/apt-stable/ $CODENAME main" > /etc/apt/sources.list.d/rspamd.list && \ 60 | apt-get update && \ 61 | apt-get --no-install-recommends install -y rspamd && \ 62 | apt-get clean && \ 63 | rm -rf /var/lib/apt/lists/* && \ 64 | echo 'pidfile = false;' > /etc/rspamd/override.d/options.inc && \ 65 | mkdir -p /srv/scripts && \ 66 | wget -O /srv/scripts/logrotate.sh https://raw.githubusercontent.com/Neomediatech/assets/main/scripts/logrotate.sh && \ 67 | chmod +x /srv/scripts/logrotate.sh 68 | 69 | COPY conf/ /etc/rspamd 70 | COPY entrypoint.sh /entrypoint.sh 71 | RUN chmod +x /entrypoint.sh 72 | 73 | HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=20 CMD rspamadm control stat |grep uptime|head -1 || ( echo "no uptime, no party\!" && exit 1 ) 74 | 75 | ENTRYPOINT ["/entrypoint.sh"] 76 | CMD [ "/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd" ] 77 | 78 | -------------------------------------------------------------------------------- /Dockerfile.latest: -------------------------------------------------------------------------------- 1 | FROM ghcr.io/rspamd/rspamd-docker 2 | 3 | ENV APP_VERSION=3.x \ 4 | SERVICE=rspamd 5 | 6 | LABEL maintainer="docker-dario@neomediatech.it" \ 7 | org.label-schema.version=$APP_VERSION \ 8 | org.label-schema.vcs-type=Git \ 9 | org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ 10 | org.label-schema.maintainer=Neomediatech 11 | 12 | USER root 13 | 14 | RUN apt-get update && \ 15 | apt-get install -y --no-install-recommends \ 16 | ca-certificates wget gosu && \ 17 | apt-get clean && \ 18 | rm -rf /var/lib/apt/lists/* 19 | 20 | SHELL ["/bin/bash", "-c"] 21 | 22 | RUN echo 'pidfile = false;' > /etc/rspamd/override.d/options.inc && \ 23 | mkdir -p /srv/scripts && \ 24 | wget -O /srv/scripts/logrotate.sh https://raw.githubusercontent.com/Neomediatech/assets/main/scripts/logrotate.sh && \ 25 | chmod +x /srv/scripts/logrotate.sh && \ 26 | chown -R 11333:11333 /etc/rspamd 27 | 28 | COPY conf/ /etc/rspamd 29 | COPY entrypoint.sh /entrypoint.sh 30 | RUN chmod +x /entrypoint.sh 31 | 32 | 33 | HEALTHCHECK --interval=30s --timeout=30s --start-period=10s --retries=20 CMD rspamadm control stat |grep uptime|head -1 || ( echo "no uptime, no party\!" && exit 1 ) 34 | 35 | ENTRYPOINT ["/entrypoint.sh"] 36 | 37 | #USER 11333:11333 38 | CMD [ "/usr/bin/rspamd", "-f" ] 39 | #CMD [ "/usr/bin/rspamd", "-f", "-u", "_rspamd", "-g", "_rspamd" ] 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dockerized Rspamd on Ubuntu 2 | Dockerized version of rspamd, based on Ubuntu. 3 | 4 | ## ToDo 5 | - LOG ROTATION. 6 | ~~`mv rspamd.log rspamd.log.1 && touch rspamd.log && chmod 666 rspamd.log` 7 | (inside the container) `kill -SIGUSR1 1` 8 | Thanks also to `tail -F `, commands above do their the job. Maybe there are better solutions (where?)~~ 9 | UPDATE: 10 | In /srv/scripts/logrotate.sh there's a script to rotate logs. It run on entrypoint.sh, prior to start rspamd. 11 | Default settings are: 12 | ``` 13 | LOG_SIZE=10485760 # after this size (in byte) the log is rotated 14 | DAYS_2_ROTATE=7 # but only after these days has been passed 15 | RETENTION=52 # how many logs to keep? 16 | ``` 17 | 18 | ## Usage 19 | You can run this container with this command: 20 | `docker run -d --name rspamd neomediatech/rspamd` 21 | 22 | Logs are written inside the container, in /var/log/rspamd/, and on stdout. You can see realtime logs running this command: 23 | `docker logs -f rspamd` 24 | `CTRL c` to stop seeing logs. 25 | 26 | If you want to map logs outside the container you can add: 27 | `-v /folder/path/on-host/logs/:/var/log/rspamd/` 28 | Where "/folder/path/on-host/logs/" is a folder inside your host. You have to create the host folder manually. 29 | 30 | You can run it on a compose file like this: 31 | 32 | ``` 33 | version: '3' 34 | 35 | services: 36 | rspamd: 37 | image: neomediatech/rspamd:latest 38 | hostname: rspamd 39 | ``` 40 | Save on a file and then run: 41 | `docker stack deploy -c /your-docker-compose-file-just-created.yml rspamd` 42 | 43 | If you want to map logs outside the container you can add: 44 | ``` 45 | volumes: 46 | - /folder/path/on-host/logs/:/var/log/rspamd/ 47 | ``` 48 | Where "/folder/path/on-host/logs/" is a folder inside your host. You have to create the host folder manually. 49 | 50 | Save on a file and then run: 51 | `docker stack deploy -c /your-docker-compose-file-just-created.yml rspamd` 52 | 53 | ### docker-compose.yml sample file: 54 | ``` 55 | # put version file you want 56 | version: 'xxx' 57 | 58 | x-environment: &common-vars 59 | TZ: Europe/Rome 60 | 61 | services: 62 | clamav: 63 | image: neomediatech/clamav:latest 64 | hostname: clamav 65 | volumes: 66 | - clamav_defs:/var/lib/clamav 67 | environment: 68 | << : *common-vars 69 | 70 | rspamd: 71 | image: neomediatech/rspamd:latest 72 | hostname: rspamd 73 | volumes: 74 | - rspamd_data:/var/lib/rspamd 75 | environment: 76 | << : *common-vars 77 | depends_on: 78 | - redis 79 | 80 | dcc: 81 | image: neomediatech/dcc:latest 82 | hostname: dcc 83 | environment: 84 | << : *common-vars 85 | 86 | razorfy: 87 | image: neomediatech/razorfy:latest 88 | hostname: razorfy 89 | environment: 90 | << : *common-vars 91 | 92 | pyzor: 93 | image: neomediatech/pyzor:latest 94 | hostname: pyzor 95 | environment: 96 | << : *common-vars 97 | 98 | redis: 99 | image: redis:alpine 100 | hostname: redis 101 | environment: 102 | << : *common-vars 103 | command: ["redis-server", "--appendonly", "yes"] 104 | volumes: 105 | - redis_db:/data 106 | 107 | volumes: 108 | common_data: 109 | driver: local 110 | webmail_app: 111 | driver: local 112 | clamav_defs: 113 | driver: local 114 | redis_db: 115 | driver: local 116 | rspamd_data: 117 | driver: local 118 | 119 | ``` 120 | 121 | ## Custom files & options 122 | - create a passowrd to access web interface: 123 | `docker run --rm -it neomediatech/rspamd` 124 | put the encrypted password in your __local.d/worker-controller.inc__ : 125 | `sed -i 's/^\(#\)\{0,1\}\( \)\{0,\}password.*/password = "your_encrypted_password";/' local.d/worker-controller.inc` 126 | or simply edit __local.d/worker-controller.inc__ and change or add the line 127 | `"password = your_encrypted_password";` 128 | - bind mount a folder in /data/local.d container to have custom configuration files, for ex: `-v /myfolder:/data/local.d` 129 | - .map and .local files found on /data directory will be "chmoded" to 666. By using rspamd web UI you can modify this files (lists and maps of ip, domains, mail addresses, etc...) 130 | 131 | 132 | | Variable | Default | Description | 133 | | -------- | ------- | ----------- | 134 | | tbd | tbd | to be done | 135 | 136 | ## Original rspamd tree, from Ubuntu 22.04 install and Rspamd 3.6, for reference 137 | ``` 138 | /etc/rspamd 139 | ├── actions.conf 140 | ├── cgp.inc 141 | ├── common.conf 142 | ├── composites.conf 143 | ├── groups.conf 144 | ├── lang_detection.inc 145 | ├── local.d 146 | ├── logging.inc 147 | ├── maps.d 148 | │   ├── dmarc_whitelist.inc 149 | │   ├── maillist.inc 150 | │   ├── mid.inc 151 | │   ├── mime_types.inc 152 | │   ├── redirectors.inc 153 | │   ├── spf_dkim_whitelist.inc 154 | │   └── surbl-whitelist.inc 155 | ├── metrics.conf 156 | ├── modules.conf 157 | ├── modules.d 158 | │   ├── antivirus.conf 159 | │   ├── arc.conf 160 | │   ├── asn.conf 161 | │   ├── aws_s3.conf 162 | │   ├── bimi.conf 163 | │   ├── chartable.conf 164 | │   ├── clickhouse.conf 165 | │   ├── dcc.conf 166 | │   ├── dkim.conf 167 | │   ├── dkim_signing.conf 168 | │   ├── dmarc.conf 169 | │   ├── elastic.conf 170 | │   ├── emails.conf 171 | │   ├── external_relay.conf 172 | │   ├── external_services.conf 173 | │   ├── force_actions.conf 174 | │   ├── forged_recipients.conf 175 | │   ├── fuzzy_check.conf 176 | │   ├── greylist.conf 177 | │   ├── hfilter.conf 178 | │   ├── history_redis.conf 179 | │   ├── http_headers.conf 180 | │   ├── maillist.conf 181 | │   ├── metadata_exporter.conf 182 | │   ├── metric_exporter.conf 183 | │   ├── mid.conf 184 | │   ├── milter_headers.conf 185 | │   ├── mime_types.conf 186 | │   ├── multimap.conf 187 | │   ├── mx_check.conf 188 | │   ├── neural.conf 189 | │   ├── once_received.conf 190 | │   ├── p0f.conf 191 | │   ├── phishing.conf 192 | │   ├── ratelimit.conf 193 | │   ├── rbl.conf 194 | │   ├── redis.conf 195 | │   ├── regexp.conf 196 | │   ├── replies.conf 197 | │   ├── reputation.conf 198 | │   ├── rspamd_update.conf 199 | │   ├── spamassassin.conf 200 | │   ├── spamtrap.conf 201 | │   ├── spf.conf 202 | │   ├── surbl.conf 203 | │   ├── trie.conf 204 | │   ├── url_redirector.conf 205 | │   └── whitelist.conf 206 | ├── options.inc 207 | ├── override.d 208 | ├── rspamd.conf 209 | ├── scores.d 210 | │   ├── content_group.conf 211 | │   ├── fuzzy_group.conf 212 | │   ├── headers_group.conf 213 | │   ├── hfilter_group.conf 214 | │   ├── mime_types_group.conf 215 | │   ├── mua_group.conf 216 | │   ├── phishing_group.conf 217 | │   ├── policies_group.conf 218 | │   ├── rbl_group.conf 219 | │   ├── statistics_group.conf 220 | │   ├── subject_group.conf 221 | │   ├── surbl_group.conf 222 | │   └── whitelist_group.conf 223 | ├── settings.conf 224 | ├── statistic.conf 225 | ├── worker-controller.inc 226 | ├── worker-fuzzy.inc 227 | ├── worker-normal.inc 228 | └── worker-proxy.inc 229 | 230 | 5 directories, 85 files 231 | ``` 232 | 233 | ## Useful infos 234 | - `options.inc` contains reference for rspamd statistics (seen in UI) 235 | stats_file = "${DBDIR}/stats.ucl"; 236 | DBDIR is (as default) /var/lib/rspamd 237 | `local.d/options.inc` to merge this file 238 | 239 | - `rspamc counters` shows stats for every symbol. Useful to know what symbols are involved 240 | 241 | - `local.d/worker-fuzzy.inc` to enable &/| fuzzy method 242 | 243 | -------------------------------------------------------------------------------- /conf/local.d/README.md: -------------------------------------------------------------------------------- 1 | in `docker-compose.yml` mount a volume to override configuration files with your own, eg: 2 | ``` 3 | volumes: 4 | - /srv/data/docker/rspamd-conf/local.d:/data/local.d 5 | ``` 6 | 7 | ## VirusTotal support 8 | Put in local.d/antivirus.conf this configuration: 9 | ``` 10 | virustotal { 11 | apikey = "your-api-key-got-from-virustotal.com"; 12 | # log_clean = true; # if you want to log also clean files 13 | } 14 | ``` 15 | -------------------------------------------------------------------------------- /conf/local.d/actions.conf: -------------------------------------------------------------------------------- 1 | reject = 13; 2 | -------------------------------------------------------------------------------- /conf/local.d/antivirus.conf: -------------------------------------------------------------------------------- 1 | clamav { 2 | # If set force this action if any virus is found (default unset: no action is forced) 3 | action = "reject"; 4 | # message = '${SCANNER}: virus found: "${VIRUS}"'; 5 | # If `max_size` is set, messages > n bytes in size are not scanned 6 | max_size = 20000000; 7 | # symbol to add (add it to metric if you want non-zero weight) 8 | symbol = "CLAM_VIRUS"; 9 | # type of scanner: "clamav", "fprot", "sophos" or "savapi" 10 | type = "clamav"; 11 | # If set true, log message is emitted for clean messages 12 | log_clean = true; 13 | # servers to query (if port is unspecified, scanner-specific default is used) 14 | # can be specified multiple times to pool servers 15 | # can be set to a path to a unix socket 16 | servers = "clamav:3310"; 17 | # `whitelist` points to a map of IP addresses. Mail from these addresses is not scanned. 18 | whitelist = "$LOCAL_CONFDIR/local.d/maps.d/antivirus_wl.map.local"; 19 | } 20 | -------------------------------------------------------------------------------- /conf/local.d/classifier-bayes.conf: -------------------------------------------------------------------------------- 1 | backend = "redis"; 2 | servers = "redis"; 3 | timeout = 20s; 4 | autolearn = true; 5 | 6 | new_schema = true; 7 | expire = 2144448000; # https://rspamd.com/doc/modules/bayes_expiry.html 8 | lazy = true; 9 | -------------------------------------------------------------------------------- /conf/local.d/dcc.conf: -------------------------------------------------------------------------------- 1 | enabled = true; 2 | servers = "dcc:10030"; 3 | timeout = 10s; 4 | log_clean = true; 5 | -------------------------------------------------------------------------------- /conf/local.d/external_services.conf: -------------------------------------------------------------------------------- 1 | razor { 2 | # servers = "127.0.0.1:11342"; 3 | servers = "razorfy:11342"; 4 | symbol = "RAZOR"; 5 | } 6 | -------------------------------------------------------------------------------- /conf/local.d/fuzzy_check.conf: -------------------------------------------------------------------------------- 1 | timeout = 5s; 2 | 3 | no_share = true; 4 | # Rspamd will now send more data when checking for fuzzy hashes: 5 | # it will send the source IP address of email being scanned and the domain name of a sender. 6 | # This data is end-to-end encrypted between you and Rspamd public fuzzy storage and I plan to use it for better spam detection. 7 | # If you don’t want this data to be shared then please stop using of the public fuzzy storage or set no_share flag to true. 8 | 9 | rule "FUZZY_CUSTOM" { 10 | # List of servers, can be an array or multi-value item 11 | servers = "127.0.0.1:11335"; 12 | 13 | symbol = "LOCAL_FUZZY_UNKNOWN"; 14 | 15 | # List of additional mime types to be checked in this fuzzy ("*" for any) 16 | #mime_types = ["application/*", "*/octet-stream"]; 17 | mime_types = ["*"]; 18 | 19 | # Maximum global score for all maps 20 | max_score = 7.0; 21 | 22 | # Ignore flags that are not listed in maps for this rule 23 | skip_unknown = yes; 24 | 25 | # If this value is false, then allow learning for this fuzzy rule 26 | read_only = no; 27 | 28 | # Fast hash type 29 | algorithm = "mumhash"; 30 | 31 | # Map flags to symbols 32 | fuzzy_map = { 33 | LOCAL_FUZZY_DENIED { 34 | # Local threshold 35 | max_score = 5.0; 36 | # Flag to match 37 | flag = 11; 38 | } 39 | LOCAL_FUZZY_PROB { 40 | max_score = 1.0; 41 | flag = 12; 42 | } 43 | LOCAL_FUZZY_WHITE { 44 | max_score = 2.0; 45 | flag = 13; 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /conf/local.d/greylist.conf: -------------------------------------------------------------------------------- 1 | enabled = false; 2 | action = "greylist"; 3 | timeout = 30s; 4 | servers = "redis"; 5 | message = ""; 6 | key_prefix = "grey:"; 7 | # expire = 1d; 8 | expire = 7d; 9 | -------------------------------------------------------------------------------- /conf/local.d/history_redis.conf: -------------------------------------------------------------------------------- 1 | servers = "redis-rspamd-history"; 2 | nrows = 5000; # nrows = 2000 # Default rows limit 3 | key_prefix = "history:"; # default is "rs_history:" 4 | compress = true; 5 | -------------------------------------------------------------------------------- /conf/local.d/logging.inc: -------------------------------------------------------------------------------- 1 | # Can be used for console logging 2 | color = true; 3 | -------------------------------------------------------------------------------- /conf/local.d/maps.d/spamtrap.map: -------------------------------------------------------------------------------- 1 | # single email address match 2 | # /^test@example\.test$/ 3 | 4 | # entire domain match 5 | # /^.*@yourspamtrapdomain\.tld$/ 6 | -------------------------------------------------------------------------------- /conf/local.d/metrics.conf: -------------------------------------------------------------------------------- 1 | symbol "DBL_BOTNET" { 2 | weight = 1.1; 3 | } 4 | 5 | symbol "MX_GOOD" { 6 | score = 0.0; 7 | } 8 | 9 | symbol "MX_INVALID" { 10 | score = 1.0; 11 | } 12 | 13 | symbol "LOCAL_BL_FROM" { 14 | score = 5.0; 15 | } 16 | 17 | symbol "LOCAL_WL_IP" { 18 | weight = -5; 19 | description = "Sender ip listed in local ip whitelist"; 20 | } 21 | 22 | #symbol "IP_REPUTATION" { 23 | # weight = 2.8; 24 | # description = "IP reputation"; 25 | #} 26 | 27 | symbol "RBL_HOSTKARMA_BLACK" { 28 | weight = 1.2; 29 | description = "NM RBL HOSTKARMA BLACK"; 30 | } 31 | 32 | group "fuzzy" { 33 | max_score = 5.0; 34 | symbol "LOCAL_FUZZY_UNKNOWN" { 35 | weight = 1.2; 36 | description = "Generic fuzzy hash match"; 37 | } 38 | symbol "LOCAL_FUZZY_DENIED" { 39 | weight = 5.0; 40 | description = "Denied fuzzy hash"; 41 | } 42 | symbol "LOCAL_FUZZY_PROB" { 43 | weight = 1.5; 44 | description = "Probable fuzzy hash"; 45 | } 46 | symbol "LOCAL_FUZZY_WHITE" { 47 | weight = -10.0; 48 | description = "Whitelisted fuzzy hash"; 49 | } 50 | } 51 | 52 | symbol "DCC_BULK" { 53 | score = 1.0; 54 | } 55 | 56 | symbol "PYZOR" { 57 | weight = 0.5; 58 | description = "Detected as spam by pyzor"; 59 | } 60 | 61 | symbol "RAZOR" { 62 | score = 1.0; 63 | description = "Detected as spam by razor"; 64 | } 65 | -------------------------------------------------------------------------------- /conf/local.d/mime_types.conf: -------------------------------------------------------------------------------- 1 | # Extensions that are treated as 'bad' 2 | # Number is score multiply factor 3 | bad_extensions = { 4 | scr = 1, 5 | lnk = 1, 6 | exe = 1, 7 | jar = 1, 8 | com = 1, 9 | bat = 1, 10 | ace = 1, 11 | arj = 1, 12 | cab = 1, 13 | asd = 1, 14 | bas = 1, 15 | chm = 1, 16 | cmd = 1, 17 | cpl = 1, 18 | crt = 1, 19 | dll = 1, 20 | hlp = 1, 21 | hta = 1, 22 | inf = 1, 23 | isp = 1, 24 | jse = 1, 25 | lib = 1, 26 | lnk = 1, 27 | mdb = 1, 28 | msi = 1, 29 | ole = 1, 30 | ocx = 1, 31 | pcd = 1, 32 | pif = 1, 33 | reg = 1, 34 | scr = 1, 35 | sys = 1, 36 | url = 1, 37 | vbe = 1, 38 | vxd = 1, 39 | }; 40 | 41 | # Extensions that are particularly penalized for archives 42 | bad_archive_extensions = { 43 | pptx = 0.1, 44 | docx = 0.1, 45 | xlsx = 0.1, 46 | pdf = 0.1, 47 | jar = 3, 48 | js = 0.5, 49 | vbs = 4, 50 | scr = 2, 51 | exe = 1, 52 | com = 1, 53 | bat = 2, 54 | pif = 2, 55 | reg = 1, 56 | url = 1, 57 | vbe = 1, 58 | vxd = 1, 59 | jse = 1, 60 | }; 61 | 62 | # Used to detect another archive in archive 63 | archive_extensions = { 64 | zip = 1, 65 | arj = 1, 66 | rar = 1, 67 | ace = 1, 68 | 7z = 1, 69 | cab = 1, 70 | }; 71 | -------------------------------------------------------------------------------- /conf/local.d/mime_types_group.conf: -------------------------------------------------------------------------------- 1 | symbols = { 2 | "MIME_GOOD" { 3 | weight = 0.0; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /conf/local.d/multimap.conf: -------------------------------------------------------------------------------- 1 | local_bl_from { 2 | type = "from"; 3 | filter = "email:domain"; 4 | map = "$LOCAL_CONFDIR/local.d/maps.d/bl_from_domain.inc.local"; 5 | symbol = "LOCAL_BL_FROM"; 6 | description = "Blacklist map for domain senders"; 7 | regexp = true; 8 | } 9 | 10 | local_wl_ip { 11 | type = "ip"; 12 | map = "$LOCAL_CONFDIR/local.d/maps.d/wl_ip.inc.local"; 13 | symbol = "LOCAL_WL_IP"; 14 | description = "IP whitelist"; 15 | } 16 | -------------------------------------------------------------------------------- /conf/local.d/mx_check.conf: -------------------------------------------------------------------------------- 1 | enabled = true; 2 | timeout = 10.0; 3 | key_prefix = "mx_check:"; 4 | greylist_invalid = true; 5 | -------------------------------------------------------------------------------- /conf/local.d/neural.conf: -------------------------------------------------------------------------------- 1 | # two training groups: SHORT last soon, LONG last more time 2 | # SHORT training can reacts quickly to newly detected patterns 3 | # for more info see https://rspamd.com/doc/modules/neural.html 4 | enabled = true; 5 | 6 | rules { 7 | "LONG" { 8 | train { 9 | max_trains = 5000; 10 | max_usages = 200; 11 | max_iterations = 25; 12 | learning_rate = 0.01, 13 | spam_score = 12; 14 | ham_score = -7; 15 | } 16 | symbol_spam = "NEURAL_SPAM_LONG"; 17 | symbol_ham = "NEURAL_HAM_LONG"; 18 | ann_expire = 100d; 19 | } 20 | "SHORT" { 21 | train { 22 | max_trains = 200; 23 | max_usages = 50; 24 | max_iterations = 25; 25 | learning_rate = 0.01, 26 | spam_score = 12; 27 | ham_score = -7; 28 | } 29 | symbol_spam = "NEURAL_SPAM_SHORT"; 30 | symbol_ham = "NEURAL_HAM_SHORT"; 31 | ann_expire = 7d; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /conf/local.d/neural_group.conf: -------------------------------------------------------------------------------- 1 | # if you are confident on your training you can increase weight to 3 and -3 2 | 3 | symbols = { 4 | "NEURAL_SPAM_LONG" { 5 | weight = 2; 6 | description = "Neural network spam (long)"; 7 | } 8 | "NEURAL_HAM_LONG" { 9 | weight = -1.0; 10 | description = "Neural network ham (long)"; 11 | } 12 | "NEURAL_SPAM_SHORT" { 13 | weight = 1; 14 | description = "Neural network spam (short)"; 15 | } 16 | "NEURAL_HAM_SHORT" { 17 | weight = -0.3; 18 | description = "Neural network ham (short)"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /conf/local.d/once_received.conf: -------------------------------------------------------------------------------- 1 | whitelist = "$LOCAL_CONFDIR/local.d/maps.d/once_received_whitelist_ip.inc.local"; 2 | -------------------------------------------------------------------------------- /conf/local.d/phishing.conf: -------------------------------------------------------------------------------- 1 | openphish_enabled = true; 2 | phishtank_enabled = true; 3 | -------------------------------------------------------------------------------- /conf/local.d/policies_group.conf: -------------------------------------------------------------------------------- 1 | symbols = { 2 | "R_SPF_ALLOW" { 3 | weight = 0.0; 4 | } 5 | 6 | "R_DKIM_ALLOW" { 7 | weight = 0.0; 8 | } 9 | 10 | "DMARC_POLICY_ALLOW" { 11 | weight = 0.0; 12 | } 13 | "DMARC_POLICY_ALLOW_WITH_FAILURES" { 14 | weight = 0.0; 15 | } 16 | 17 | "DMARC_POLICY_REJECT" { 18 | weight = 5.0; 19 | } 20 | 21 | "DMARC_POLICY_QUARANTINE" { 22 | weight = 2; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /conf/local.d/ratelimit.conf: -------------------------------------------------------------------------------- 1 | # some mad experience, we disable it 2 | enabled = false; 3 | -------------------------------------------------------------------------------- /conf/local.d/rbl_group.conf: -------------------------------------------------------------------------------- 1 | symbols = { 2 | "RBL_SPAMHAUS_CSS" { 3 | weight = 4.0; 4 | } 5 | 6 | "RBL_SPAMHAUS_PBL" { 7 | weight = 1.0; 8 | description = "From address is listed in zen pbl (ISP list)"; 9 | } 10 | 11 | "RBL_SENDERSCORE" { 12 | weight = 2.5; # more trust to senderscore than default 2.0 13 | description = "From address is listed in senderscore.com BL"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /conf/local.d/redis.conf: -------------------------------------------------------------------------------- 1 | servers = "redis"; 2 | timeout = 20s; 3 | -------------------------------------------------------------------------------- /conf/local.d/replies.conf: -------------------------------------------------------------------------------- 1 | key_prefix = "replies:"; 2 | timeout = 10s; 3 | symbol = "REPLY"; 4 | -------------------------------------------------------------------------------- /conf/local.d/spamtrap.conf: -------------------------------------------------------------------------------- 1 | enabled = false; # enable it if you want to setup a spamtrap. Put regex rules in local.d/maps.d/spamtrap.map 2 | 3 | action = "reject"; 4 | score = 13.0; 5 | learn_fuzzy = true; 6 | learn_spam = true; 7 | fuzzy_flag = 11; # flag number on LOCAL_FUZZY_DENIED rule in local.d/fuzzy_check.conf 8 | # fuzzy_weight = 10.0; # A weight factor for the fuzzy rule. It defaults to 10.0 9 | map = file://$LOCAL_CONFDIR/local.d/maps.d/spamtrap.map; 10 | -------------------------------------------------------------------------------- /conf/local.d/spf.conf: -------------------------------------------------------------------------------- 1 | # 28 gen 2020 : list of authorized IP/NETS addresses to forward 2 | external_relay = "$LOCAL_CONFDIR/local.d/maps.d/spf_external_relays.map.local"; 3 | -------------------------------------------------------------------------------- /conf/local.d/statistics_group.conf: -------------------------------------------------------------------------------- 1 | symbols = { 2 | "BAYES_SPAM" { 3 | weight = 6.0; 4 | description = "Message probably spam, probability: "; 5 | } 6 | "BAYES_HAM" { 7 | weight = -5.0; 8 | description = "Message probably ham, probability: "; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /conf/local.d/url_reputation.conf: -------------------------------------------------------------------------------- 1 | enabled = true; 2 | key_prefix = "url_rep:"; 3 | -------------------------------------------------------------------------------- /conf/local.d/url_tags.conf: -------------------------------------------------------------------------------- 1 | enabled = true; 2 | key_prefix = "url_tags:"; 3 | expire = 1800s; 4 | -------------------------------------------------------------------------------- /conf/local.d/whitelist.conf: -------------------------------------------------------------------------------- 1 | rules { 2 | "WHITELIST_SPF" = { 3 | score = -2.0; # one minus point than default -1.0 score 4 | description = "(LOCAL) Mail comes from the whitelisted domain and has a valid SPF policy"; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /conf/local.d/worker-controller-readme.txt: -------------------------------------------------------------------------------- 1 | # This file is only an example on what you have to do to enable Rspamd web interface. 2 | # Replace "secure_ip" line with an IP address that can connect to the interface without enter the password. 3 | # Repeat "secure_ip" lines as many IP addresses you want to enable the access without password. 4 | # For any other IP replace ${PASSWORD} with an encrypted password generate by the command 5 | # docker run --rm -it neomediatech/rspamd rspamadm pw 6 | # After you can rename this file as worker-controller.inc 7 | # 8 | bind_socket = "0.0.0.0:11334"; 9 | secure_ip = "127.0.0.1"; 10 | password = "${PASSWORD}"; 11 | #enable_password = "${PASSWORD}"; 12 | -------------------------------------------------------------------------------- /conf/local.d/worker-fuzzy.inc: -------------------------------------------------------------------------------- 1 | # Number of processes to serve this storage (useful for read scaling) 2 | count = 4; 3 | 4 | # Backend ("sqlite" or "redis" - default "sqlite") 5 | backend = "redis"; 6 | 7 | # sqlite: Where data file is stored (must be owned by rspamd user) 8 | # database = "${DBDIR}/fuzzy.db"; 9 | 10 | # Hashes storage time (3 months) 11 | expire = 90d; 12 | 13 | # Synchronize updates to the storage each minute 14 | sync = 1min; 15 | 16 | allow_update = ["127.0.0.1"]; 17 | -------------------------------------------------------------------------------- /conf/local.d/worker-normal.inc: -------------------------------------------------------------------------------- 1 | bind_socket = "*:11333"; 2 | -------------------------------------------------------------------------------- /conf/plugins.d/__razor.lua__: -------------------------------------------------------------------------------- 1 | local logger = require "rspamd_logger" 2 | local tcp = require "rspamd_tcp" 3 | 4 | local N = "razor" 5 | local symbol_razor = "RAZOR" 6 | local opts = rspamd_config:get_all_opt(N) 7 | 8 | -- Default settings 9 | local cfg_host = "127.0.0.1" 10 | local cfg_port = 9192 11 | 12 | local function check_razor(task) 13 | local function cb(err, data) 14 | if err then 15 | logger.errx(task, "request error: %s", err) 16 | return 17 | end 18 | local resp = tostring(data) 19 | if resp == "spam" then 20 | task:insert_result(symbol_razor, 1.0) 21 | logger.debugm(N, task, "spam") 22 | elseif resp == "ham" then 23 | logger.debugm(N, task, "ham") 24 | else 25 | logger.errx(task, "unknown response from razorsocket: %s", resp) 26 | end 27 | end 28 | 29 | local msg_size = task:get_size() 30 | if msg_size > 1000000 then 31 | local logger = require "rspamd_logger" 32 | logger.infox(task, "message size is too big: %s", msg_size) 33 | task:insert_result(symbol_razor, 0.0, 'message size is too big: ' .. msg_size) 34 | else 35 | tcp.request({ 36 | task = task, 37 | host = cfg_host, 38 | port = cfg_port, 39 | shutdown = true, 40 | data = task:get_content(), 41 | callback = cb, 42 | }) 43 | end 44 | end 45 | 46 | if opts then 47 | if opts.host then 48 | cfg_host = opts.host 49 | end 50 | if opts.port then 51 | cfg_port = opts.port 52 | end 53 | 54 | rspamd_config:register_symbol({ 55 | name = symbol_razor, 56 | callback = check_razor, 57 | }) 58 | else 59 | logger.infox("%s module not configured", N) 60 | end 61 | -------------------------------------------------------------------------------- /conf/plugins.d/pyzor.lua: -------------------------------------------------------------------------------- 1 | local ucl = require "ucl" 2 | local logger = require "rspamd_logger" 3 | local tcp = require "rspamd_tcp" 4 | 5 | local N = "pyzor" 6 | local symbol_pyzor = "PYZOR" 7 | local opts = rspamd_config:get_all_opt(N) 8 | 9 | -- Default settings 10 | local cfg_host = "localhost" 11 | local cfg_port = 5953 12 | 13 | --{"PV": "2.1", "Code": "200", "WL-Count": "0", "Count": "53", "Thread": "53416", "Diag": "OK"} 14 | 15 | local function check_pyzor(task) 16 | local function cb(err, data) 17 | if err then 18 | logger.errx(task, "request error: %s", err) 19 | return 20 | end 21 | logger.debugm(N, task, 'data: %s', tostring(data)) 22 | 23 | local parser = ucl.parser() 24 | local ok, err = parser:parse_string(tostring(data)) 25 | if not ok then 26 | logger.errx(task, "error parsing response: %s", err) 27 | return 28 | end 29 | 30 | local resp = parser:get_object() 31 | local whitelisted = tonumber(resp["WL-Count"]) 32 | local reported = tonumber(resp["Count"]) 33 | 34 | logger.infox(task, "count=%s wl=%s", reported, whitelisted) 35 | 36 | -- Make whitelists count a little bit. 37 | -- Maybe there's a better way to take whitelists into account, 38 | -- but at least this is something. 39 | reported = reported - whitelisted 40 | 41 | local weight = 0 42 | 43 | if reported >= 100 then 44 | weight = 1.5 45 | elseif reported >= 25 then 46 | -- weight = 1.25 47 | weight = 1.0 48 | elseif reported >= 15 then 49 | weight = 0.7 50 | -- elseif reported >= 5 then 51 | -- weight = 1.0 52 | -- elseif reported >= 1 and whitelisted == 0 then 53 | -- weight = 0.2 54 | end 55 | 56 | if whitelisted > 100 then 57 | weight = 0 58 | end 59 | 60 | if weight > 0 then 61 | task:insert_result(symbol_pyzor, weight, string.format("count=%d wl=%d", reported, whitelisted)) 62 | end 63 | end 64 | 65 | local request = { 66 | "CHECK\n", 67 | task:get_content(), 68 | } 69 | 70 | logger.debugm(N, task, "querying pyzor") 71 | 72 | tcp.request({ 73 | task = task, 74 | host = cfg_host, 75 | port = cfg_port, 76 | shutdown = true, 77 | data = request, 78 | callback = cb, 79 | }) 80 | end 81 | 82 | if opts then 83 | if opts.host then 84 | cfg_host = opts.host 85 | end 86 | if opts.port then 87 | cfg_port = opts.port 88 | end 89 | 90 | rspamd_config:register_symbol({ 91 | name = symbol_pyzor, 92 | callback = check_pyzor, 93 | }) 94 | else 95 | logger.infox("%s module not configured", N) 96 | end 97 | -------------------------------------------------------------------------------- /conf/rspamd.conf.local: -------------------------------------------------------------------------------- 1 | # use neomediatech/razorfy-docker instead 2 | # razor { 3 | # host = razor; 4 | # port = 9192; 5 | # } 6 | 7 | pyzor { 8 | host = pyzor; 9 | port = 5953; 10 | } 11 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | antispam: 2 | build: . 3 | environment: 4 | PASSWORD: 'apassword' 5 | volume_driver: local 6 | volumes: 7 | - "filter:/var/lib/rspamd" 8 | ports: 9 | - 11334:11334 10 | - 11333:11333 11 | 12 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PWCLEAR="$(echo {A..Z} {a..z} {0..9} {0..9} '@ # % ^ ( ) _ + = - [ ] { } . ?' | tr ' ' "\n" | shuf | xargs | tr -d ' ' | cut -b 1-12)" 4 | PWCRYPT="$(rspamadm pw -e -p $PWCLEAR)" 5 | 6 | SECURE_IP=${SECURE_IP:-"127.0.0.1"} 7 | PASSWORD=${PASSWORD:-"$PWCRYPT"} 8 | #ENABLE_PASSWORD=${ENABLE_PASSWORD:-$PASSWORD} 9 | 10 | # Check custom configuration files 11 | CUSTOM_CONF_BASE_DIR="/data" 12 | CUSTOM_CONF_DIRS="local.d override.d plugins.d" 13 | for DIR in $CUSTOM_CONF_DIRS; do 14 | CUSTOM_CONF_DIR="$CUSTOM_CONF_BASE_DIR/$DIR" 15 | if [ -d "$CUSTOM_CONF_DIR" ]; then 16 | echo "Checking for custom configuration files in ${CUSTOM_CONF_DIR}..." 17 | find "$CUSTOM_CONF_DIR" -maxdepth 1 -type f -name '[!.]*.*' -printf "%f\n"| while read CONFIG_FILE ; do 18 | if [ -f "/etc/rspamd/${DIR}/${CONFIG_FILE}" ]; then 19 | echo " WARNING: ${CONFIG_FILE} already exists and will be overriden" 20 | rm -f "/etc/rspamd/${DIR}/${CONFIG_FILE}" 21 | fi 22 | echo " Add custom config file ${CONFIG_FILE}..." 23 | [ ! -d "/etc/rspamd/${DIR}/" ] && mkdir -p "/etc/rspamd/${DIR}/" 24 | [ "${CONFIG_FILE##*.}" = "map" -o "${CONFIG_FILE##*.}" = "local" ] && chmod 666 "/data/${DIR}/${CONFIG_FILE}" 25 | ln -sf "/data/${DIR}/${CONFIG_FILE}" "/etc/rspamd/${DIR}/" 26 | done 27 | fi 28 | done 29 | 30 | if [ -d "$CUSTOM_CONF_BASE_DIR/local.d/maps.d" ]; then 31 | mv "/etc/rspamd/local.d/maps.d" "/etc/rspamd/local.d/maps.d.orig" 32 | ln -s "$CUSTOM_CONF_BASE_DIR/local.d/maps.d" "/etc/rspamd/local.d/maps.d" 33 | chown _rspamd "$CUSTOM_CONF_BASE_DIR/local.d/maps.d" 34 | chmod 666 "$CUSTOM_CONF_BASE_DIR/local.d/maps.d/*" 35 | fi 36 | 37 | # Check for custom rspamd.conf config 38 | GLOBAL_CUSTOM_CONF_FILE="$CUSTOM_CONF_BASE_DIR/local.d/rspamd.conf.local" 39 | if [ -f $GLOBAL_CUSTOM_CONF_FILE ]; then 40 | echo "Add custom config file rspamd.conf.local" 41 | rm -f /etc/rspamd/rspamd.conf.local 42 | ln -sf $CUSTOM_CONF_BASE_DIR/local.d/rspamd.conf.local /etc/rspamd/ 43 | fi 44 | 45 | if [ ! -f /etc/rspamd/local.d/worker-controller.inc ]; then 46 | cat << EOF > /etc/rspamd/local.d/worker-controller.inc 47 | bind_socket = "0.0.0.0:11334"; 48 | secure_ip = "${SECURE_IP}"; 49 | password = "${PASSWORD}"; 50 | #enable_password = "${PASSWORD}"; 51 | EOF 52 | echo " " 53 | echo " " 54 | echo " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" 55 | echo " " 56 | echo " THE PASSWORD TO ACCESS THE WEB UI IS: $PWCLEAR" 57 | echo " " 58 | echo " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" 59 | echo " " 60 | echo " " 61 | else 62 | echo " " 63 | echo " " 64 | echo " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" 65 | echo " IF YOU DIDN'T SET '\$PASSWORD' VARIABLE" 66 | echo " OR IF YOU DON'T KNOW WHAT I'M SAYING" 67 | echo " AND YOU DON'T KNOW THE PASSWORD TO ACCESS" 68 | echo " THE WEB UI, THEN ENTER THE CONTAINER AND" 69 | echo " DELETE THE FILE /etc/rspamd/local.d/worker-controller.inc" 70 | echo " THEN RESTART THE CONTAINER AND SHOW THE CONSOLE LOGS" 71 | echo " THE PASSWORD WILL BE PUT ON THE SCREEN" 72 | echo " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" 73 | echo " " 74 | echo " " 75 | fi 76 | 77 | LOGFILE="/var/log/rspamd/rspamd.log" 78 | 79 | [ ! -d /var/log/rspamd ] && mkdir -p /var/log/rspamd 80 | [ ! -d /run/rspamd ] && mkdir -p /run/rspamd && chown _rspamd:_rspamd /run/rspamd 81 | [ -d /var/lib/rspamd ] && chown _rspamd:_rspamd /var/lib/rspamd 82 | 83 | [ ! -f $LOGFILE ] && touch $LOGFILE && chown _rspamd:_rspamd $LOGFILE 84 | 85 | if [ -f /srv/scripts/logrotate.sh ]; then 86 | chmod +x /srv/scripts/logrotate.sh 87 | /srv/scripts/logrotate.sh /var/log/rspamd/ 88 | fi 89 | 90 | cmd="/dockerize" 91 | if [ -x "$cmd" ]; then 92 | checks="" 93 | if [ -n "$WAITFOR" ]; then 94 | for CHECK in $WAITFOR; do 95 | checks="$checks -wait $CHECK" 96 | done 97 | $cmd $checks -timeout 180s -wait-retry-interval 15s 98 | [ $? -ne 0 ] && exit 1 99 | fi 100 | fi 101 | 102 | exec tail -F $LOGFILE & 103 | #rspamd -i -f 104 | exec gosu _rspamd "$@" 105 | -------------------------------------------------------------------------------- /rspamd-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Neomediatech/rspamd/7e56f2d4119907dd03458860f42a42163d527eea/rspamd-logo.png --------------------------------------------------------------------------------