Trimite email prin Mailgun pe Rocky Linux 9 / CentOS 9

Pentru trimiterea de email-uri se poate folosi un serviciu extern. Tutorialul arată ce și cum să instalezi/configurezi Rocky Linux 9 / CentOS 9 pentru a trimite email-urile prin Mailgun.

Condiții prealabile

Asigură-te că ai configurat înainte Mailgun și ai la îndemână host, utilizator, parolă. De asemenea trebuie să configurezi firewall-ul să permită traficul OUTGOING pe portul 2525/TCP.

Instalare și configurare Postfix

Instalarea este simplă:

# dnf install postfix cyrus-sasl-plain cyrus-sasl-md5

Apoi configurăm serviciului proaspăt instalat:

# vim /etc/postfix/main.cf

În acest fișier, căutăm, decomentăm dacă este nevoie, și setăm conform instrucțiunilor:
– myhostname
– mydomain
– myorigin

Mai departe urmează secțiunea relayhost unde setăm astfel:

relayhost = [smtp.eu.mailgun.org]:2525

La finalul fișierului modificăm sau adăugam următoarele configurări:

smtp_tls_security_level = encrypt
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous

Salvăm fișierul și-l închidem. La smtp_sasl_password_maps am specificat un fișier, prin urmare trebuie să-l creăm:

# cat > /etc/postfix/sasl_passwd << EOF

Apoi scriem astfel:

> [smtp.eu.mailgun.org]:2525 MAILGUN_USER:MAILGUN_PASS
> EOF

Folosim apoi postmap pentru a genera un fișier .db, apoi ștergem fișierul care conține parola în clar și setăm permisiunile fișierului .db:

# postmap /etc/postfix/sasl_passwd
# rm /etc/postfix/sasl_passwd
# chmod 600 /etc/postfix/sasl_passwd.db

În final pornim postfix și am terminat

# systemctl start postfix
# systemctl enable postfix

Cam atât a fost. Totul trebuie să funcționeze excelent.

Testarea

Putem face și un test, dar pentru asta avem nevoie de s-nail (care înlocuiește mailx de la versiunile mai vechi)

# dnf install s-nail

Apoi dăm comanda pentru a fi trimis un email

# echo 'Test passed.' | mail -s 'Test-Email' adresa_email@example.com

Dacă vrei să vezi și în loguri, folosește comanda:

# tail -n 5 /var/log/maillog

Instalare Rocky Linux 8/CentOS8 + NGINX + PHP-FPM + MariaDB + Let’s Encrypt

Acest tutorial te ajută să îţi configurezi un server web cu Rocky Linux 8/CentOS8, NGINX, PHP-FPM, MariaDB şi Let’s Encrypt.

Instalarea va fi făcută cu ultimele versiuni stabile disponibile la momentul de faţă. Pachetele sunt din repository-uri oficiale, acolo unde dezvoltatorii au asa ceva. Toate comenzile sunt executate ca root. În cazul în care foloseşti un utiliazator fără drepruri, adaugă sudo în faţa fiecărei comenzi.

Cele mai recente versiuni stabile la momentul scrierii/actualizării acestui articol:

Rocky Linux 8.4 / CentOS 8.4
Nginx 1.20.1 stable
PHP 8.0.11
MariaDB 10.6.4
Certbot 1.20.0 (pentru Let's Encrypt)

Urmează pas cu pas instrucţiunile de mai jos şi vei obţine un server funcţional cu specificaţiile software de mai sus.

Cuprins:
1. Câteva lucruri necesare
2. Securizare server
3. Instalare MariaDB
4. Instalare Nginx
5. Instalare și configurare PHP
6. Configurare Nginx
7. Instalare Let’s Encrypt

1. Câteva lucruri necesare

Instalează câteva pachete necesare pentru configurarea serverului şi repository-ul EPEL

# dnf install -y vim wget dnf-utils epel-release

Microtutorial pentru vim

Fişierul se deschide cu comanda

# vim <fişier>

Ca să scrii text în fişier, intră în modul de inserare apăsând “i” sau “INSERT” şi apoi poţi scrie.
Ca să adaugi un text din clipboard, după ce intri în modul de inserare, apasă SHIFT+INSERT sau click dreapta.
Pentru a salva şi închide fişierul, întâi ieşi din modul de inserare apăsând tasta “ESC”, apoi scrie textul de mai jos şi apasă ENTER

:x

Pentru a căuta un text, ieși din modul de inserare (cu ESC) și apoi apasă /

2. Securizare server

După instalarea inițială a Rocky Linux / CentOS, verifică dacă există actualizări ale sistemului de operare

# dnf update -y

Dezactivează login-ul cu root. Dar mai întâi de asta, crează un nou utilizator cu care să intri. Dacă vei folosi parola pentru autentificare, setează și o parolă.

# useradd -m -U -s /bin/bash -G wheel mynewuser
# passwd mynewuser

Configurăm utilizatorul să nu solicite parola atunci când apelează comenzi cu sudo, mai ales dacă se face conectarea prin cheie SSH și nu prin parolă. Pentru asta trebuie creat un fișier în /etc/sudoers.d/ . Să-i spunem 01-local-users.

# vim /etc/sudoers.d/01-local-users

Adaugă în el conținutul de mai jos:

# Created manually

# User rules for root
mynewuser ALL=(ALL) NOPASSWD:ALL

Dacă te conectezi cu o cheie SSH, nu uita să adaugi cheia pe noul utilizator, fișierul /home/mynewuser/.ssh/authorized_keys

Editează /etc/ssh/sshd_config

# vim /etc/ssh/sshd_config

Câteva setări de securitate în acest fișier cuprind: blocarea conectării cu utilizatorul root la server, setarea unui timeout pentru sesiune, specificarea utilizatorilor permiși pentru autentificare, schimbarea portului de conectare la SSH și blocarea conectării după un număr de conectări eșuate. Pentru toate acestea, modifică, decomentează sau adaugă următoarele setări:

PermitRootLogin no
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers mynewuser
Port 12345
MaxAuthTries 2

După salvarea fișierului, testează corectitudinea configurărilor, și dacă totul este OK, restartează serviciul

# sshd -t
# systemctl restart sshd

Securizează serverul (cu firewall) ca să nu ai surprize. De asemenea va fi nevoie să permiți accesul la protocoalele HTTP și HTTPS.

# dnf install -y firewalld
# systemctl start firewalld
# systemctl enable firewalld
# firewall-cmd --zone=public --permanent --add-service=http
# firewall-cmd --zone=public --permanent --add-service=https
# firewall-cmd --reload

Nu uita să adaugi în firewall noul port pentru SSH și să elimini conectarea prin portul implicit

# firewall-cmd –zone=public –permanent –add-port=12345/tcp
# firewall-cmd –zone=public –permanent –remove-service=ssh
# firewall-cmd –reload

3. Instalare MariaDB

Dacă instalezi MariaDB din repository-ul Rocky Linux / CentOS, ar instala versiunea 10.3 (la momentul actual). MariaDB are repository oficial, aşa că îl adăugăm şi vom folosi versiunea 10.6.

# vim /etc/yum.repos.d/MariaDB.repo

Adaugă codul de mai jos în fişierul deschis şi se salvează-l

[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.6/centos8-amd64
module_hotfixes=1
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

Instalează MariaDB, porneşte serviciul şi activează-l să pornească automat la reboot

# dnf install -y MariaDB-server MariaDB-client
# systemctl start mariadb
# systemctl enable mariadb

Rulează scriptul de securizare pentru MariaDB şi setează o parola pentru root

# mariadb-secure-installation

4. Instalare Nginx

Pentru a adăuga repository-ul oficial Nginx, crează fişierul Nginx.repo în /etc/yum.repos.d

# vim /etc/yum.repos.d/nginx.repo

Adaugă codul de mai jos în fişier şi se salvează-l

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

Instalează Nginx, porneşte serviciul şi activează-l să pornească automat la reboot

# dnf install -y nginx
# systemctl start nginx
# systemctl enable nginx

Verifică instalarea apelând serverul prin browser.

5. Instalare și configurare PHP

PHP-ul nu are un repository oficial, aşa că apelăm la unul extern care conţine pachetele necesare. Vom folosi REMI.

# dnf install -y http://rpms.remirepo.net/enterprise/remi-release-8.rpm

În acest moment, sunt disponibile mai multe versiuni de PHP disponibile. Ca să poţi instala PHP din REMI, trebuie să activezi versiunea dorită. În cazul de faţă, ultima versiune stabilă este PHP 8.0

# dnf -y module enable php:remi-8.0

Acum poţi instala PHP-FPM.

# dnf install -y php-fpm php-mysqlnd php-common php-json php-pdo php-cli php-gd php-xml

În funcţie de necesitățile aplicației/site-ului, trebuie să instalezi pachetele necesare și specifice acestuia.

Nota: pachetul php (simplu) nu a fost instalat şi nici nu este nevoie să fie instalat. Acel pachet este necesar doar când foloseşti PHP împreună cu Apache.

O recomandare pentru o (mică) îmbunătăţire a securităţii este să editezi php.ini

# vim /etc/php.ini

şi să setezi

cgi.fix_pathinfo=0

Păstrăm motivul şi mai facem încă o schimbare. Implicit, PHP afişează versiunea în header-ul primit de browser. Pentru a elimina versiunea, în același fișier, caută şi setează

expose_php = Off

Editează www.conf

# vim /etc/php-fpm.d/www.conf

Folosind nginx, trebuie schimbaţi parametrii user şi group

user = nginx
group = nginx

Decomentează parametrii listen.owner şi listen.group şi stetează-i corect

listen.owner = nginx
listen.group = nginx

Porneşte PHP-FPM şi activează-l să pornească automat

# systemctl start php-fpm
# systemctl enable php-fpm

Notă: În acest moment, Nginx nu este configurat să servească pagini PHP.

6. Configurare Nginx

Nginx crează un fişier implicit de configurare pentru domeniu. Este nevoie să-l modificăm

# vim /etc/nginx/conf.d/default.conf

Mai jos sunt modificările, dar la final ai un exemplu de fişier cu toate acestea (pentru subdomeniul casastii.nanlucian.com ca exemplu), păstrând comentariile implicite Nginx şi adăugând altele pentru secţiunile noi, dar eliminând directivele comentate şi nefolosite. Schimbările sunt:

  • setează server_name cu (sub)domeniul tău
  • în secţiunea location / { } găseşti directivele root şi index. Mută-le un “nivel” mai sus, în server { }
  • adaugă index.php în index (de preferat ar fi primul)
  • în secţiunea location / { } adaugă try_files $uri $uri/ =404;
  • decomentează error_page   404 /404.html;
  • decomentează secţiuna location ~ \.php$ { } şi adaugă şi acolo linia try_files $uri $uri/ =404;

Exemplu cu modificările făcute (ce este cu roșu este modificat față de configurarea default, dar mare parte trebuie și modificate conform nevoilor):

server {
    listen 80;
    server_name casastii.nanlucian.com;

    #urmatoarele 2 linii sunt mutate din location / { }
    root /var/www/html; #trebuie configurată calea corectă
    index index.php index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }

    error_page 404 /404.html; # linie decomentata

    # redirect server error pages to the static page /50x.html
    #
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }

    # pass the PHP scripts to FastCGI server listening on /run/php-fpm/www.sock
    # sectiunea de mai jos era comentata
    location ~ \.php$ {
        try_files $uri $uri/ =404;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    location ~ /\.ht {
        deny all;
    }
}

Recomand să schimbi numele fişierului din default.conf în <domeniu>.conf .

Implicit, Nginx afişează versiunea în header-ul primit de browser. Din motive de securitate, este de preferat să dezactivezi afişarea versiunii. O poţi face tot în fişierul /etc/nginx/nginx.conf . În secţiunea http { } adaugă

# vim /etc/nginx/nginx.conf
server_tokens off;

Nu uita ca după ce finalizezi modificările în Nginx, să verifici sintaxa fişierelor de configurare şi (în caz că nu există nicio eroare) să dai restart la serviciu.

# nginx -t
# systemctl restart nginx

7. Instalare Let’s Encrypt

Este impropriu spus instalare Let’s Encrypt, pentru că acesta doar emite certificatele SSL/TLS. Deoarece valabilitatea certificatelor este de doar 90 de zile, ar fi de preferat ca aceste certificate să se reînnoiască automat. Pentru aceasta vom instala CertBot

# dnf install certbot python3-certbot-nginx

Generare certificat SSL/TLS

Având domeniul/domeniile configurate în Nginx, poţi genera certificatele SSL/TLS. La generarea cu comanda de mai jos, Certbot va oferi posibilitatea de a modifica fişierele de configurare Nginx, astfel încât să configureze automat redirecţionarea către HTTPS şi folosirea certificatelor. Dacă vrei să faci tu aceste modificări, manual, adaugă la final: certonly

# certbot --nginx

Şi cum spuneam mai sus, ar fi de preferat ca aceste certificate să se reînnoiască automat. Pentru asta editează cron-ul

# crontab -e

şi adaugă o linie similară cu cea de mai jos (Certbot recomandă de 2 ori/zi). La linia de mai jos, recomand să schimbaţi orele scrise.

0 1,14 * * * root python -c 'import random; import time; time.sleep(random.random() * 3600)' && /usr/bin/certbot renew

Pentru crearea unei mașini virtuale (VM), multe servicii de hosting oferă posibilitatea utilizării cloud-init pentru o configurare inițială mai rapidă. Am creat un fișier pe care-l poți folosi ca template pentru secțiunea cloud-config. Trebuie făcute câteva modificări, menționate chiar în fișier.
Notă: fișierul pentru cloud-init a fost actualizat ultima dată pe configurația: CentOS 7.6, Nginx 1.14.2, PHP 7.3.1, MariaDB 10.3.12, Modul Google PageSpeed 1.13.35, Certbot 0.29.1 (pentru Let’s Encrypt).

webserver.cloud-init

dkim-filter: smfi_opensocket() failed

dkimÎncă un post într-o limbă străină (de data asta despre DKIM) pentru cei care nu au nicio treabă cu calculatoarele, însă, aşa cum am scris în postul iniţial, aici găsiţi problemele care mi-au dat de cap şi cum le-am rezolvat. Unele ajută o categorie de oameni, altele altă categorie şi tot aşa. Oricum, probabil că nu vor mai fi în următoarea perioadă posturi despre servere deoarece mă apropii de finalizat reconfigurarea unui server şi îmi mut focusul. Dar să trecem la subiect.

DKIM-milter semnează e-mail-urile care urmează a fi trimise de acel server. Se setează în Postfix ca mailurile să treacă mai întâi pe la semnarea DKIM. N-o să intru în detalii despre acest lucru pentru că nu acesta este subiectul (mai discutăm în comentarii dacă este cazul).

Eroarea era la încercarea de a porni dkim-milter şi era cât se poate de aiurea:

/etc/init.d/dkim-milter start
Starting DomainKeys Identified Mail Milter (dkim-filter): dkim-filter: smfi_opensocket() failed
                       [FAILED]

În momentul în care apărea această eroare, în /var/log/maillog scria:

Jun 10 21:16:48 nutrienti dkim-filter[6758]: Sendmail DKIM Filter: Unable to bind to port inet:8891@localhost: Cannot assign requested address
Jun 10 21:16:48 nutrienti dkim-filter[6758]: Sendmail DKIM Filter: Unable to create listening socket on conn inet:8891@localhost
Jun 10 21:16:48 nutrienti dkim-filter[6758]: smfi_opensocket() failed

Eu nu mă aştept ca pentru toată lumea să existe aceeaşi rezolvare, însă pentru cei care au serverul configurat similar, e posibil să dea de problema aceasta.

Practic dkim-milter încerca să asculte pe 8891@localhost conform setărilor din /etc/sysconfig/dkim-milter .
Problema a fost că localhost este setat ca IPv6 şi el încerca să se conecteze la 8891@::1 . Singurul lucru pe care l-am făcut a fost să schimb 8891@localhost cu 8891@127.0.0.1 .

Pentru a putea folosi serviciul prin Postfix, trebuie schimbat şi în Postfix acest lucru.

UPDATE 25.02.2015

Eroarea anterioară am primit-o în CentOS 6.X. Trecând la CentOS 7, am avut surpriza să dau din nou de această eroare (norocul meu că mai erau şi alte detalii acolo). Situaţia: dkim-milter pornea prima dată după instalare, însa după reboot, dădea failed. Intrând în investigaţii am constatat că dispărea folderul /var/run/dkim-milter şi singura soluţie găsită a fost să creez un script, care la fiecare reboot să fie lansat şi să creeze folderul înainte să încerce programul să se lanseze.

Scriptul (să-i spunem startdkim.sh):

#!/bin/bash
mkdir /var/run/dkim-milter
chown dkim-milter:dkim-milter /var/run/dkim-milter

Acesta se poate pune oricunde. De exemplu în /root/cron_scripts/startdkim.sh . Se face scriptul executabil:

cd /root/cron_scripts
chmod +x startdkim.sh

Apoi se editează crontab

crontab -e

şi se adaugă în prima linie să pornească la fiecare reboot:

@reboot /root/cron_scripts/startdkim.sh > /dev/null 2>&1

pcfg_openfile: unable to check htaccess file, ensure it is readable

Distracţia mereu începe atunci când primeşti o eroare… eronată. Pentru că eroarea a apărut dintr-un alt motiv decât este explicată. Aşa am întâmpinat eu această eroare la mutarea unui site de pe un server pe altul.

[Wed Jun 05 18:34:26 2013] [error] [client 2a02:2f0e:c0d0:98:d8ef::fc99:3969] PHP Warning: imagepng(): Unable to open ‘./images/captcha/feb84f81d7590126da1c977fe975583c.png’ for writing: Permission denied in /var/www/library/Zend/Captcha/Image.php on line 563
[Wed Jun 05 18:34:26 2013] [crit] [client 2a02:2f0e:c0d0:98:d8ef::fc99:3969] (13)Permission denied: /var/www/sub.domeniu.com/public_html/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://sub.domeniu.com/

La o astfel de eroare, m-am întrebat “de unde .htaccess acolo, pentru ca nu a fost niciodată?” Studiind puţin problema am constatat de fapt că nu erau suficiente drepturi pentru apache ca să scrie imaginea în directorul captcha. Este singurul lucru pe care l-am făcut ca să funcţioneze totul din nou şi să nu mai primesc eroarea. După cum se vede, nu are nicio legătură cu eroarea în sine.

Sugestie: verificaţi drepturile directorului începând de la document_root al (sub)domeniului respectiv. Nu a fost nevoie să dau permisiuni doar directorului captcha, ci şi la images. De asemenea, drepturi necesare nu au fost de scriere sau citire, ci de execuţie (+x).

Succes!

Crontab pe scurt

Semnificaţia parametrilor

*  *  *  *  *   comanda de executat
│ │ │ │ │
│ │ │ │ │
│ │ │ │ └───── ziua săptămânii (0 – 6) (0 este Duminică, sau foloseşte numele în eng)
│ │ │ └────────── luna (1 – 12)
│ │ └─────────────── ziua din lună (1 – 31)
│ └──────────────────── ora (0 – 23)
└───────────────────────── minutul (0 – 59)

Se asemeni se poate folosi şi pentru a executa fişierele (şi nu numai) din X în X… ce vrei tu.
De exemplu pentru a rula un fişier din 5 în 5 minute, foloseşte

*/5 * * * * /calea/către/fişier

Dacă mai ai alte remarci de făcut, lasă un comentariu.