Napisano dnia 6.08.2021 r. o godzinie 7:00
Autor: Piotr Sperka
Witam Cię w piątym odcinku serii pod tytułem VPS dla początkujących. Po pracach z poprzednich części mamy już uruchomione podstawowe usługi. Dzisiaj zajmiemy się czymś nieco bardziej złożonym — uruchomimy serwer e-mail. Użyjemy do tego połączenia Postfixa i Dovecota, oraz Roundcube jako webmaila. Aby zaoszczędzić sobie pracy, wykorzystamy Mailu, które łączy w sobie te usługi w wygodnej formie kontenerów Dockerowych.
Wygenerowanie pliku docker-compose.yml
dla Mailu jest bardzo proste. Przechodzimy do strony setup.mailu.io, wybieramy stabilną wersję i generujemy potrzebne pliki, korzystając z kreatora. Opcje musisz dostosować pod swoją konfigurację, jednak pamiętaj, że wszystko, co wyklikasz w konfiguratorze, możesz potem łatwo zmienić w wygenerowanych plikach. Oto przykładowa konfiguracja, którą otrzymałem.
docker-compose.yml:
version: '2.2' services: # External dependencies redis: image: redis:alpine restart: always volumes: - "/docker/mailu/redis:/data" # Core services front: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}nginx:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env logging: driver: json-file ports: - "25:25" - "465:465" - "587:587" - "110:110" - "995:995" - "143:143" - "993:993" expose: - 80 - 443 volumes: - "/docker/mailu/certs:/certs" - "/docker/mailu/overrides/nginx:/overrides" networks: - default - reverse_proxy admin: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}admin:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env volumes: - "/docker/mailu/data:/data" - "/docker/mailu/dkim:/dkim" depends_on: - redis imap: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}dovecot:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env volumes: - "/docker/mailu/mail:/mail" - "/docker/mailu/overrides:/overrides" depends_on: - front smtp: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}postfix:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env volumes: - "/docker/mailu/overrides:/overrides" depends_on: - front antispam: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}rspamd:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env volumes: - "/docker/mailu/filter:/var/lib/rspamd" - "/docker/mailu/dkim:/dkim" - "/docker/mailu/overrides/rspamd:/etc/rspamd/override.d" depends_on: - front # Webmail webmail: image: ${DOCKER_ORG:-mailu}/${DOCKER_PREFIX:-}roundcube:${MAILU_VERSION:-1.7} restart: always env_file: mailu.env volumes: - "/docker/mailu/webmail:/data" depends_on: - imap # Database mailu-db: image: mariadb:latest restart: always environment: MYSQL_DATABASE: mailu MYSQL_USER: mailu MYSQL_PASSWORD: tajnehaslo MYSQL_RANDOM_ROOT_PASSWORD: '1' volumes: - /docker/mailu/mysql:/var/lib/mysql networks: - default - reverse_proxy networks: default: driver: bridge ipam: driver: default config: - subnet: 192.168.203.0/24 reverse_proxy: external: true
mailu.env:
################################### # Common configuration variables ################################### # Set to a randomly generated 16 bytes string SECRET_KEY=0123456789ABCDEF # Subnet of the docker network. This should not conflict with any networks to which your system is connected. (Internal and external!) SUBNET=192.168.203.0/24 # Main mail domain DOMAIN=twoja-domena.pl # Hostnames for this server, separated with comas HOSTNAMES=twoja-domena.pl,mail.twoja-domena.pl # Postmaster local part (will append the main mail domain) POSTMASTER=admin # Choose how secure connections will behave (value: letsencrypt, cert, notls, mail, mail-letsencrypt) TLS_FLAVOR=mail # Authentication rate limit (per source IP address) AUTH_RATELIMIT=60/minute;2500/hour # Opt-out of statistics, replace with "True" to opt out DISABLE_STATISTICS=False ################################### # Optional features ################################### # Expose the admin interface (value: true, false) ADMIN=true # Choose which webmail to run if any (values: roundcube, rainloop, none) WEBMAIL=roundcube # Dav server implementation (value: radicale, none) WEBDAV=none # Antivirus solution (value: clamav, none) ANTIVIRUS=none ################################### # Mail settings ################################### # Message size limit in bytes # Default: accept messages up to 50MB # Max attachment size will be 33% smaller MESSAGE_SIZE_LIMIT=50000000 # Networks granted relay permissions # Use this with care, all hosts in this networks will be able to send mail without authentication! RELAYNETS= # Will relay all outgoing mails if configured RELAYHOST= # Fetchmail delay FETCHMAIL_DELAY=600 # Recipient delimiter, character used to delimiter localpart from custom address part RECIPIENT_DELIMITER=+ # DMARC rua and ruf email DMARC_RUA=admin DMARC_RUF=admin # Welcome email, enable and set a topic and body if you wish to send welcome # emails to all users. WELCOME=false WELCOME_SUBJECT=Welcome to your new email account WELCOME_BODY=Welcome to your new email account, if you can read this, then it is configured properly! # Maildir Compression # choose compression-method, default: none (value: bz2, gz) COMPRESSION= # change compression-level, default: 6 (value: 1-9) COMPRESSION_LEVEL= ################################### # Web settings ################################### # Path to redirect / to WEBROOT_REDIRECT=/webmail # Path to the admin interface if enabled WEB_ADMIN=/admin # Path to the webmail if enabled WEB_WEBMAIL=/webmail # Website name SITENAME=Mail # Linked Website URL WEBSITE=https://twoja-domena.pl ################################### # Advanced settings ################################### # Log driver for front service. Possible values: # json-file (default) # journald (On systemd platforms, useful for Fail2Ban integration) # syslog (Non systemd platforms, Fail2Ban integration. Disables `docker-compose log` for front!) # LOG_DRIVER=json-file # Docker-compose project name, this will prepended to containers names. COMPOSE_PROJECT_NAME=mailu # Default password scheme used for newly created accounts and changed passwords # (value: BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT, MD5-CRYPT, CRYPT) PASSWORD_SCHEME=BLF-CRYPT # Header to take the real ip from REAL_IP_HEADER= # IPs for nginx set_real_ip_from (CIDR list separated by commas) REAL_IP_FROM= # choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no) REJECT_UNLISTED_RECIPIENT= # Log level threshold in start.py (value: CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET) LOG_LEVEL=WARNING ################################### # Database settings ################################### DB_FLAVOR=mysql DB_USER=mailu DB_PW=tajnehaslodobazy DB_HOST=mailu-db DB_NAME=mailu
W teorii jedyne co musimy teraz zrobić to wykonać polecenie docker-compose up
. W praktyce jednak okazało się, że plik wygenerował się błędnie. Wersja obrazów zamiast 1.7 była oznaczona jako 1_7, przez co nie było możliwości ich pobrania. Ponadto do pliku docker-compose.yml
postanowiłem dodać również bazę danych. Z uwagi na używane zewnętrzne reverse proxy, zmieniłem również ustawienia portów w kontenerze mailu/nginx
. Koniec końców, uzyskałem pliki docker-compose.yml
oraz mailu.env
takie, jak przedstawione powyżej. Oczywiście, z inną domeną oraz kluczem. Tym razem kontenery uruchomiły się poprawnie. Kolejnym krokiem było skopiowanie certyfikatów do katalogu /docker/mailu/certs
.
cp /etc/letsencrypt/live/<twoja-domena>/fullchain.pem cert.pem cp /etc/letsencrypt/live/<twoja-domena>/privkey.pem key.pem
Istotne jest, aby wykonać kopię plików, a nie jedynie dowiązania symboliczne. Nie znam dokładnej przyczyny, jednak same dowiązania symboliczne nie przyniosły pożądanych efektów. Dodałem również kolejny blok server do pliku nginx.conf
:
server { server_name mail.twoja-domena.pl; location / { include /etc/nginx/includes/proxy.conf; proxy_pass http://front:80; } listen 443 ssl; ssl_certificate /etc/letsencrypt/live/twoja-domena.pl/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/twoja-domena.pl/privkey.pem; }
Po tym wykonałem polecenia docker-compose down
oraz docker-compose up
w katalogu /docker/mailu
, a także zrestartowałem reverse proxy. Otwarłem również w firewallu porty odpowiedzialne za IMAP, POP3 oraz SMTP, wszystkie z szyfrowaniem:
ufw allow 465/tcp ufw allow 993/tcp ufw allow 995/tcp
Na potrzeby debugowania, dopóki nie uzyskamy działającej usługi, warto pominąć przełącznik -d
podczas uruchamiania Mailu poprzez docker-compose. Kontenery zostaną wówczas uruchomione bez zwalniania konsoli i pojawią się w niej bieżące logi.
TLS_FLAVOR=notls
w pliku mailu.env
. Jeśli po tej zmianie i restarcie kontenerów panel zadziała, oznacza to, że jest jakiś problem z certyfikatami. Ponadto musisz upewnić się, czy zmienne DOMAIN oraz HOSTNAMES są ustawione prawidłowo.Jeśli udało się wyświetlić stronę logowania do panelu administracyjnego, przyszedł czas na stworzenie konta administratora. Zrobimy to poleceniem wykonanym z katalogu /docker/mailu
:
docker-compose exec admin flask mailu admin root twoja-domena.pl tajnehaslo123
Polecenie te stworzy konto administratora o loginie i haśle
tajnehaslo123
. Tymi danymi logujemy się do panelu administracyjnego, gdzie możemy dodać kolejnych użytkowników, dodać aliasy, i tak dalej (zakładka domeny pocztowe).
Pozostało jeszcze skonfigurować domenę. Wpisy, jakie powinniśmy dodać w konfiguracji DNS naszej domeny, znajdziemy w menu pod pozycją Domeny pocztowe po kliknięciu ikony „Szczegóły” przy wybranej domenie. Jeżeli dotąd nie wygenerowałeś kluczy DKIM, zrobisz to, klikając na Wygeneruj klucze we wspomnianej zakładce.
Gdy wszystko jest ustawione, możemy spróbować czy poczta działa. Przechodzimy do mail.twoja-domena.pl/webmail i logujemy się na wybrane z założonych kont. Na początek sugeruję wysłać maila na drugie konto w tej samej domenie. Jeśli wiadomość dojdzie, możemy wypróbować konfigurację domeny i serwera. Do tego można wykorzystać wiele różnych serwisów. Ja testowałem poprzez https://www.mail-tester.com/. Test polega na wysłaniu dowolnej wiadomości (najlepiej z sensownym tekstem) na wyświetlony na stronie adres, a następnie kliknięciu sprawdź. Otrzymamy wynik i informacje o ewentualnych problemach w konfiguracji. W moim wypadku uzyskałem wynik 10/10, co oznacza, że wszystko jest ok.
Zauważyłem też jeszcze jedną zależność. Mniejszą szansę na trafienie na listę „podejrzanych” domen mamy mając domenę ze „starej” puli, na przykład com, pl, eu, info, org, itp. „Nowe” domeny jak na przykład online, tech, host, i tak dalej mają z nieznanej mi do końca przyczyny większe szanse na trafienie do spamu. Nie będę się już nawet rozpisywał o takim detalu jak różne walidatory w formularzach. Przykładowo, próba wysłania pliku JPK do urzędu skarbowego zakończy się błędem walidacji, jeśli podamy mail z domeną kończącą się na .online.
Podsumowując, dzisiaj udało nam się uruchomić funkcjonujący serwer e-mail, obsługujący protokoły IMAP, POP3 oraz SMTP wraz z obsługą szyfrowania, oraz webmailem. W kolejnym i prawdopodobnie ostatnim odcinku zajmiemy się dodatkowym zabezpieczeniem serwera, kwestią automatycznego odświeżania certyfikatów oraz ostatecznymi szlifami.
Jak zawsze zapraszam do kontaktu i do następnego 😉