SSD Nodes Learn Hosting plans →
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-07

VPS वर Listmonk newsletter स्वतः host कसे करावे

Ubuntu 24.04 वर Listmonk v6.2.0, PostgreSQL 16, config.toml, systemd आणि TLS सेट करा. SMTP जोडल्यानंतर delivery reputation तयार होण्यास काही आठवडे लागतात.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

Listmonk वरील self-hosted newsletter साठी आवश्यक बाबी

Listmonk हे self-hosted newsletter आणि mailing list व्यवस्थापक आहे: एक Go binary, एक PostgreSQL database, एक config file आणि एक systemd unit. छोटा VPS हे सहज चालवू शकतो, कारण Listmonk subscribers आणि campaigns ची queue साठवतो; मात्र तो स्वतः ईमेल वितरित करत नाही. तो प्रत्येक संदेश SMTP (simple mail transfer protocol) server कडे सोपवतो. त्यामुळे तुमचा delivery rate या software मुळे नव्हे, तर त्या server च्या reputation मुळे ठरतो.

या मार्गदर्शकात Ubuntu 24.04 वर Listmonk v6.2.0, म्हणजे July 2026 पर्यंतचे current release, install केले आहे. तुमच्याकडे public IP address असलेला VPS, तुमच्या नियंत्रणाखालील domain name आणि PostgreSQL 12 किंवा त्यानंतरची आवृत्ती असणे आवश्यक आहे. Install पूर्ण होण्यासाठी साधारण एक तास लागतो. Sending reputation तयार होण्यासाठी काही आठवडे लागतात. त्या प्रक्रियेचे वर्णन शेवटच्या भागाजवळ केले आहे.

PostgreSQL स्थापित करा आणि डेटाबेस तयार करा

Ubuntu 24.04 च्या स्वतःच्या repository मध्ये PostgreSQL 16 उपलब्ध आहे. Listmonk साठी आवश्यक आवृत्तीपेक्षा ही आवृत्ती बरीच नवीन आहे.

sudo apt update
sudo apt install -y postgresql curl
sudo systemctl enable --now postgresql

एकाच psql session मध्ये role आणि database तयार करा. -v ON_ERROR_STOP=1 मुळे पहिल्या अयशस्वी statement नंतर psql बंद होते. त्यामुळे एखाद्या typo मुळे अर्धवट setup पूर्ण झाल्यासारखे दिसत नाही.

sudo -u postgres psql -v ON_ERROR_STOP=1 <<'SQL'
CREATE USER listmonk WITH PASSWORD 'pick-a-long-random-password';
CREATE DATABASE listmonk OWNER listmonk;
SQL

OWNER listmonk हे केवळ सजावटीसाठी नाही. Schema install करताना tables, types, indexes आणि functions तयार होतात. त्यामुळे role कडे database ची मालकी असणे आवश्यक आहे. दुसऱ्या role च्या मालकीच्या database कडे Listmonk निर्देशित केल्यास, तुम्ही GRANT CONNECT चालवलेले असले तरी install permission denied सह थांबते.

पुढे जाण्यापूर्वी database अस्तित्वात आहे याची खात्री करा.

sudo -u postgres psql -tAc "SELECT datname FROM pg_database WHERE datname='listmonk';"

यामुळे listmonk प्रदर्शित होते. रिकामी ओळ दिसल्यास CREATE statement चाललेले नाही. त्यामुळे psql चे output पुन्हा तपासा.

Listmonk binary स्थापित करा

Listmonk प्रत्येक architecture साठी static binary प्रकाशित करते. आधी तुमचे architecture तपासा, कारण ARM VPS वर amd64 binary ही kernel execute करण्यास नकार देणारी फाइल असते.

dpkg --print-architecture
cd /tmp
curl -fsSLO https://github.com/knadh/listmonk/releases/download/v6.2.0/listmonk_6.2.0_linux_amd64.tar.gz
tar -xzf listmonk_6.2.0_linux_amd64.tar.gz
sudo install -m 755 listmonk /usr/bin/listmonk
listmonk --version

ARM VPS वर file name मधील amd64 ऐवजी arm64 वापरा. listmonk --version version string छापत असल्यास binary या machine शी जुळते याचा हा पहिला पुरावा आहे.

config.toml तयार करा आणि त्याच्या परवानग्या मर्यादित करा

--new-config सध्याच्या working directory मध्ये config.toml लिहिते. त्यामुळे cd हे sh -c च्या आत असते, sudo च्या आधी नाही.

sudo install -d -m 750 /etc/listmonk
sudo sh -c 'cd /etc/listmonk && listmonk --new-config'

तयार झालेली फाइल लहान असते. [app] अंतर्गत address = "localhost:9000" HTTP server ला फक्त loopback वर bind करते. त्यामुळे reverse proxy समोर ठेवत नाही तोपर्यंत admin panel इंटरनेटवरून उपलब्ध होत नाही. ती ओळ बदलू नका. [db] अंतर्गत host = "localhost", port = 5432, user = "listmonk", database = "listmonk" आणि ssl_mode = "disable" मिळतात. हे default values तुम्ही तयार केलेल्या database शी आधीच जुळतात. त्यामुळे तुम्हाला बदलायची एकमेव ओळ म्हणजे password.

Postgres त्याच मशीनवरील loopback वर listening करत असेल, तर ssl_mode = "disable" योग्य आहे, कारण तो network traffic मशीनबाहेर जात नाही. Database दुसऱ्या host वर हलवल्यास ते require वर सेट करा; अन्यथा password network वर cleartext मध्ये पाठवला जाईल.

[db] अंतर्गत password ची ओळ role शी जुळेल अशी संपादित करा. त्यानंतर service account तयार करा आणि ही फाइल इतर सर्व login पासून सुरक्षित ठेवा.

sudo useradd --system --home-dir /var/lib/listmonk --create-home --shell /usr/sbin/nologin listmonk
sudo chown -R root:listmonk /etc/listmonk
sudo chmod 640 /etc/listmonk/config.toml

आता service account ही फाइल वाचू शकते आणि इतर कोणीही ती वाचू शकत नाही.

sudo -u listmonk cat /etc/listmonk/config.toml > /dev/null && echo readable
stat -c '%U:%G %a' /etc/listmonk/config.toml

पहिली command readable दाखवते. दुसरी root:listmonk 640 दाखवते. इतर कोणतेही unprivileged account त्याच cat चा प्रयत्न केल्यास Permission denied मिळते. यामागचा उद्देश हा आहे: या फाइलमध्ये तुमचा database password cleartext मध्ये आहे आणि server वर सामान्यतः एकापेक्षा अधिक login असतात. तुम्ही चालवत असलेल्या प्रत्येक service साठी हाच नियम लागू होतो. त्यामुळे किमान आवश्यक privilege असलेले service users वाचा आणि तो सर्वत्र लागू करा.

--install वापरून schema तयार करा

--install tables तयार करते आणि default settings भरते. environment variables वापरून पहिला admin login सेट करा, जेणेकरून panel उपलब्ध होण्यापूर्वीच account तयार होईल.

sudo -u listmonk env LISTMONK_ADMIN_USER=admin \
  LISTMONK_ADMIN_PASSWORD='another-long-random-password' \
  listmonk --config /etc/listmonk/config.toml --install --yes

--yes confirmation prompt ला उत्तर देते. ते automate करण्यापूर्वी हा prompt एकदा वाचा, कारण --install ही first-time installer आहे आणि ती आधीपासून अस्तित्वात असलेला Listmonk schema हटवते. Live database वर ती दुसऱ्यांदा चालवल्यास subscribers नष्ट होतात. दोनदा चालू शकणाऱ्या कोणत्याही script मध्ये --install --idempotent --yes वापरा. Tables आधीपासून असल्यास ते काहीही करत नाही. नवीन release मध्ये आलेले schema changes --upgrade वापरून लागू करा; --install वापरू नका.

Browser ऐवजी database कडून result तपासा.

sudo -u postgres psql -d listmonk -c '\dt'
sudo -u postgres psql -d listmonk -tAc "SELECT username FROM users;"

पहिली command Listmonk tables ची यादी दाखवते. त्यात subscribers, lists, campaigns, templates आणि bounces यांचा समावेश असतो. दुसरी command admin दाखवते. दुसऱ्या command कडून रिकामा result मिळाल्यास environment variables process पर्यंत पोहोचलेले नाहीत. त्यामुळे panel त्याऐवजी browser मध्ये पहिला user तयार करण्यास सांगेल.

systemd अंतर्गत Listmonk चालवा

/etc/systemd/system/listmonk.service लिहा.

[Unit]
Description=Listmonk newsletter and mailing list manager
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=simple
User=listmonk
Group=listmonk
WorkingDirectory=/var/lib/listmonk
ExecStart=/usr/bin/listmonk --config /etc/listmonk/config.toml
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

WorkingDirectory महत्त्वाचे आहे, कारण Listmonk filesystem media upload path यांसह relative paths त्याच्या आधारावर resolve करते. After=postgresql.service फक्त startup क्रम ठरवते. ती Postgres कडून connections स्वीकारले जाण्याची प्रतीक्षा करत नाही. त्यामुळे Listmonk थोडे लवकर सुरू होऊन connect करू शकत नाही, ही परिस्थिती Restart=on-failure हाताळते.

sudo systemctl daemon-reload
sudo systemctl enable --now listmonk
ss -ltnp | grep 9000
curl -sI http://127.0.0.1:9000/

ss मध्ये 127.0.0.1:9000 LISTEN स्थितीत दिसले पाहिजे. curl ने कोणतीही HTTP status line परत केल्यास server प्रतिसाद देत आहे. curl Connection refused सह fail झाल्यास startup दरम्यान process बंद झाला आहे. त्याचे कारण journalctl -u listmonk -n 50 --no-pager मध्ये दिसेल. लक्षात ठेवा, reboot नंतर टिकून राहणारा भाग enable --now आहे: हाताने सुरू केलेला process पुढील kernel upgrade नंतर बंद होतो.

nginx आणि TLS पुढे ठेवा

Listmonk loopback वर plain HTTP वापरते. त्यामुळे nginx TLS (transport layer security) समाप्त करून विनंती पुढे पाठवते.

server {
    listen 443 ssl;
    server_name lists.example.com;

    client_max_body_size 25m;

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Subscriber imports आणि media uploads हे file posts असल्यामुळे client_max_body_size वाढवणे आवश्यक आहे. nginx डीफॉल्टनुसार 1 MB पेक्षा मोठ्या कोणत्याही post ला 413 Request Entity Too Large सह नाकारते. certbot वापरून certificate जारी करा. ते तुमच्यासाठी listen 443 ssl ओळी आणि port 80 वरून redirect देखील लिहिते: पायऱ्या nginx साठी Let's Encrypt certificate मार्गदर्शक येथे आहेत. Ports 80 आणि 443 उघडा आणि 9000 बंद ठेवा, कारण proxy त्याच्यापर्यंत loopback द्वारे पोहोचतो. Firewall मध्ये अद्याप कोणतेही बदल केले नसतील, तर ufw firewall मूलतत्त्वे पासून सुरुवात करा.

त्यानंतर admin panel उघडा आणि Settings अंतर्गत root URL म्हणून https://lists.example.com सेट करा. नवीन install मध्ये http://localhost:9000 असते. Listmonk email मध्ये लिहिलेल्या प्रत्येक unsubscribe link आणि media URL मध्ये ही value वापरते. ही value बदलण्यापूर्वी campaign पाठवल्यास प्रत्येक recipient ला स्वतःच्या मशीनकडे निर्देश करणारे links मिळतात. ते reader साठी अपयशी ठरतात. Spam filter ला असे वाटू शकते की sender स्वतःचे domain configure करू शकत नाही.

config.toml मध्ये नसलेले SMTP जोडा

config.toml मध्ये SMTP विभाग शोधला, तरी तो सापडणार नाही. मेल सेटिंग्ज database मधील settings table मध्ये असतात आणि त्या admin panel मधील Settings आणि SMTP अंतर्गत संपादित करता येतात. त्यामुळे निर्माण होणारी file इतकी लहान राहते. SMTP मध्ये बदल केल्यावर restart करण्याची गरज नसते, याचे कारणही हेच आहे.

SMTP server साठी दोन व्यवहार्य पर्याय आहेत. स्वतःचा SMTP server चालवा. त्यामुळे त्याची reputation पूर्णपणे तुमच्या नियंत्रणात राहते; मात्र हा स्वतंत्रपणे पूर्ण करावा लागणारा प्रकल्प आहे: Mailcow वापरून स्वतःचा mail server चालवणे यामध्ये त्यासाठी आवश्यक बाबी स्पष्ट केल्या आहेत. किंवा Listmonk ला transactional relay कडे निर्देशित करा आणि IP reputation ची जबाबदारी दुसऱ्या सेवेला द्या.

दोन्हीपैकी कोणताही पर्याय वापरताना STARTTLS सह port 587 किंवा implicit TLS सह port 465 वापरा. outbound port 25 वर अवलंबून राहू नका. नवीन खात्यांवर बहुतेक VPS providers तो default ने block करतात. Port 25 block असल्यास connection अडकलेले दिसते, कारण packets नाकारले जात नाहीत तर drop केले जातात. त्यामुळे client त्वरित fail न होता timeout ची प्रतीक्षा करतो.

त्यावर विश्वास ठेवण्यापूर्वी चाचणी करा. एक list तयार करा, subscriber म्हणून तुमचा स्वतःचा address जोडा आणि एक recipient असलेली campaign पाठवा. प्राप्त झालेला message उघडा आणि पूर्ण headers वाचा. Receiving side ने जोडलेला Authentication-Results header SPF आणि DKIM pass झाले आहेत की नाही ते सांगतो.

डिलिव्हरेबिलिटी हेच संपूर्ण काम

Listmonk संदेश तयार करते, यादीचा मागोवा घेते आणि मेल पुढे पाठवते. तो मेल inbox मध्ये पोहोचेल की नाही यासंबंधी प्रत्येक निर्णय प्राप्त करणारा provider घेतो. यासाठी तो sending IP address आणि sending domain वापरतो. नवीन VPS IP चा कोणताही इतिहास नसतो. मोठे mailbox provider असा इतिहास नसणे किंचित संशयास्पद मानतात.

चार गोष्टी अनिवार्य आहेत:

  • तुमच्या domain साठी पाठवण्याची परवानगी असलेल्या host चे नाव देणारा SPF (sender policy framework) TXT record.
  • TXT record म्हणून प्रकाशित केलेली DKIM (domainkeys identified mail) key. तिचे signing Listmonk ने नव्हे, तर mail server ने केलेले असावे.
  • DMARC (domain based message authentication, reporting and conformance) record. पहिल्या दोन तपासण्या अयशस्वी झाल्यास प्राप्त करणाऱ्या provider ने काय करावे, हे तो सांगतो.
  • Listmonk वाचू शकेल असा bounce mailbox. त्यामुळे मेल नाकारणारे addresses पुन्हा पुन्हा वापरण्याऐवजी यादीतून काढले जातात.

त्यानंतर सुरुवातीला मेल हळूहळू पाठवा. ज्या domain ने यापूर्वी कधीही मेल पाठवलेला नाही आणि अचानक एका तासात दहा हजार संदेश पाठवले, तो compromised account सारखाच दिसतो. त्यामुळे त्याचे messages filtering मध्ये अडकतात. सर्वाधिक सक्रिय subscribers पासून सुरुवात करा आणि काही दिवसांत volume वाढवा.

प्रत्येक template मध्ये कार्यरत unsubscribe link देखील आवश्यक आहे. Listmonk template मध्ये तो {{ UnsubscribeURL }} आहे. Campaign body {{ template "content" . }} ज्या ठिकाणी आहे त्या ठिकाणी येतो आणि प्रत्येक template मध्ये तो नेमका एकदाच असला पाहिजे. Unsubscribe link नसलेल्या campaign मुळे unsubscribes ऐवजी spam complaints मिळतात. अनेक आठवडे निर्माण केलेली sending reputation गमावण्याचा हा सर्वात जलद मार्ग आहे.

बॅकअप आणि restore साठी प्रत्यक्षात आवश्यक असलेल्या गोष्टी

दोन गोष्टी server च्या बाहेर ठेवणे आवश्यक आहे: database dump आणि config.toml. Campaigns मध्ये images upload करत असल्यास media directory देखील समाविष्ट करा.

sudo -u postgres pg_dump -Fc listmonk > listmonk-$(date +%F).dump

त्या dump मध्ये subscribers, campaigns, templates आणि SMTP credentials सहित प्रत्येक setting साठवलेली असते. त्यामुळे तो encrypt करून या server च्या बाहेर ठेवा. हे schedule करण्याची समस्या आधीच सोडवलेली आहे: remote storage वर encrypted restic backups पहा. config.toml मध्ये काही ओळी असतात, परंतु त्यात database password असतो. त्यामुळे त्याच पद्धतीने त्याचे संरक्षण करा.

Upgrades एका निश्चित क्रमाने करा. Service थांबवा, dump घ्या, /usr/bin मधील binary बदला, listmonk --config /etc/listmonk/config.toml --upgrade चालवा आणि त्यानंतर service सुरू करा. Schema migrations फक्त पुढील दिशेने चालतात. त्यामुळे मागील स्थितीत परत जाण्यासाठी तो dump हाच एकमेव मार्ग आहे.

Listmonk सुरू करण्यात अपयशी का ठरते?

प्रथम journalctl -u listmonk -n 50 --no-pager वापरून journal वाचा. जवळजवळ प्रत्येक startup failure चे कारण [db] block मध्ये एका ओळीत दिसते.

pq: password authentication failed for user "listmonk" याचा अर्थ [db] मधील password Postgres role शी जुळत नाही. pq prefix म्हणजे Postgres driver server ने नकार दिल्याची नोंद करत आहे. त्यामुळे config योग्यरीत्या वाचली गेली आहे आणि credentials चुकीचे आहेत. sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" वापरून role reset करा आणि file मध्ये तोच string लिहा.

pq: database "listmonk" does not exist याचा अर्थ [db] मधील database value प्रत्यक्ष database चे नाव नाही. sudo -u postgres psql -l server वर प्रत्यक्ष उपलब्ध असलेले databases दाखवते. त्यात तुम्ही चुकीने वापरलेले spelling देखील दिसेल.

permission denied हे --install दरम्यान दिसल्यास role connect होऊ शकते; परंतु database तिच्या मालकीचा नसतो. त्यामुळे त्या database मध्ये tables तयार करता येत नाहीत. sudo -u postgres psql -c "ALTER DATABASE listmonk OWNER TO listmonk;" वापरून दुरुस्ती करा आणि install पुन्हा चालवा.

Service कधीही सुरू होत नाही आणि journal मध्ये config file चे नाव दिसते. listmonk म्हणून चालणारी process, mode 600 असलेली root:root म्हणून ठेवलेली config.toml उघडू शकत नाही. stat -c '%U:%G %a' /etc/listmonk/config.toml ने root:listmonk 640 दाखवले पाहिजे आणि त्यावरील directory root:listmonk 750 असली पाहिजे.

Panel काम करते, परंतु mail येत नाही. ही startup समस्या नाही. प्रथम Settings आणि SMTP तपासा. त्यानंतर admin panel मधील campaign चा स्वतःचा log तपासा. प्रत्येक प्रयत्नासाठी mail server ने परत केलेली error त्यात नोंदवलेली असते.

FAQ

Listmonk वापरण्यासाठी माझा स्वतःचा mail server आवश्यक आहे का?

नाही. Listmonk हा mail server नाही. तुमचा mail स्वीकारून तो वितरित करणाऱ्या server ची SMTP credentials त्याला आवश्यक असतात. हा server transactional relay किंवा तुम्ही स्वतः चालवत असलेला mail server असू शकतो. Admin panel मधील Settings आणि SMTP अंतर्गत ही credentials सेट करा. ती config.toml मध्ये सेट करू नका, कारण mail settings database मध्ये साठवल्या जातात. STARTTLS सह port 587 किंवा implicit TLS सह port 465 वापरा, कारण बहुतेक VPS providers नवीन accounts साठी outbound port 25 block करतात.

Root URL setting अजूनही तिच्या install default http://localhost:9000 वर आहे. Campaign पाठवताना Listmonk ही value unsubscribe links आणि media URLs मध्ये लिहिते. Admin panel मधील Settings उघडा, root URL तुमच्या प्रत्यक्ष HTTPS address वर सेट करा आणि save करा. आधीच वितरित केलेल्या messages मध्ये दुरुस्ती करता येत नाही. त्यामुळे प्रत्यक्ष list ला mail करण्यापूर्वी स्वतःला test campaign पाठवा आणि त्यातील unsubscribe link वर click करा.

--install पुन्हा चालवल्यास माझे subscribers हटतील का?

होय. --install हा first-time installer आहे आणि तो विद्यमान Listmonk schema drop करतो. --yes मुळे तुम्हाला सावध करणारा prompt काढला जातो. दोनदा चालू शकणाऱ्या कोणत्याही script मध्ये --install --idempotent --yes वापरा. Tables आधीपासून अस्तित्वात असल्यास ते काहीही करत नाही. नवीन release मधील schema changes लागू करण्यासाठी service थांबवा, pg_dump घ्या आणि त्यानंतर --upgrade चालवा.

Listmonk user listmonk साठी password authentication failed असे का सांगते?

/etc/listmonk/config.toml मधील [db] block मध्ये दिलेला password त्याच नावाच्या Postgres role शी जुळत नाही. Journal मधील line pq: password authentication failed for user "listmonk" अशी आहे. pq हा Postgres driver ने server कडून मिळालेला rejection पुढे पाठवलेला संदेश आहे. यावरून config file सापडली आणि वाचली गेली हे स्पष्ट होते. sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" वापरून role चा password reset करा, तोच string config file मध्ये लिहा आणि त्यानंतर sudo systemctl restart listmonk चालवा.