SSD Nodes Learn 8GB RAM — $66/वर्ष
मार्गदर्शक Matt Connorद्वारे Matt Connor · अपडेटेड 2026-08-01

VPS वर Listmonk स्वयं-होस्ट करून वृत्तपत्र कसे चालवावे

Ubuntu 24.04 वर Listmonk v6.2.0, PostgreSQL 16, config.toml, systemd आणि TLS स्थापित करा. SMTP जोडा आणि वितरणक्षमतेचा खरा खर्च समजून घ्या.

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

Listmonk वर स्वयं-होस्ट केलेल्या वृत्तपत्रासाठी आवश्यक गोष्टी

Listmonk हे स्वयं-होस्ट केलेले वृत्तपत्र आणि मेलिंग सूची व्यवस्थापक आहे: एक Go बायनरी, एक PostgreSQL डेटाबेस, एक कॉन्फिगरेशन फाइल आणि एक systemd युनिट. लहान VPS वर ते सहज चालते, कारण Listmonk सदस्यांची माहिती साठवते आणि मोहिमांसाठी संदेश रांगेत ठेवते; मात्र ते स्वतः ईमेल वितरित करत नाही. ते प्रत्येक संदेश SMTP (simple mail transfer protocol) सर्व्हरकडे पाठवते. त्यामुळे तुमचा वितरण दर या सॉफ्टवेअरऐवजी त्या सर्व्हरच्या प्रतिष्ठेवर ठरतो.

या मार्गदर्शकात Ubuntu 24.04 वर Listmonk v6.2.0, म्हणजे July 2026 पर्यंतची सध्याची आवृत्ती, स्थापित केली आहे. तुमच्याकडे सार्वजनिक IP पत्ता असलेला VPS, तुमच्या नियंत्रणाखालील डोमेन नाव आणि PostgreSQL 12 किंवा त्यानंतरची आवृत्ती असणे आवश्यक आहे. स्थापना पूर्ण होण्यासाठी सुमारे एक तास लागतो. प्रेषणाची प्रतिष्ठा निर्माण होण्यासाठी काही आठवडे लागतात. त्या भागाचे वर्णन शेवटी केले आहे.

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 निर्देशित केल्यास permission denied सह install थांबते, GRANT CONNECT चालवलेले असले तरीही.

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

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

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

Listmonk बायनरी स्थापित करा

Listmonk प्रत्येक आर्किटेक्चरसाठी एक static binary प्रकाशित करते. प्रथम तुमचे आर्किटेक्चर तपासा, कारण 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 मशीनशी जुळत असल्याचा तुमचा पहिला पुरावा आहे.

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

--new-config सध्याच्या कार्यरत निर्देशिकेत 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 internet वरून पोहोचण्यायोग्य नसते. ती ओळ बदलू नका. [db] अंतर्गत तुम्हाला host = "localhost", port = 5432, user = "listmonk", database = "listmonk" आणि ssl_mode = "disable" मिळतात. ही default मूल्ये तुम्ही तयार केलेल्या database शी आधीच जुळतात. त्यामुळे बदलणे आवश्यक असलेली एकमेव ओळ म्हणजे password.

Postgres त्याच box वर 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 साठी हेच तत्त्व लागू होते. म्हणून किमान विशेषाधिकार असलेले 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 ला उत्तर देते. Automation करण्यापूर्वी तो prompt एकदा वाचा, कारण --install ही installer ची पहिली वेळची प्रक्रिया आहे आणि ती विद्यमान Listmonk schema हटवते. Live database वर ती दुसऱ्यांदा चालवल्यास subscribers नष्ट होतात. दोनदा चालू शकणाऱ्या कोणत्याही script मध्ये --install --idempotent --yes वापरा. Tables आधीच अस्तित्वात असतील, तर ते काहीही करत नाही. नवीन release मध्ये समाविष्ट केलेले schema बदल --upgrade ने लागू करा; --install ने कधीही करू नका.

परिणाम browser ऐवजी database कडून तपासा.

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 सापेक्ष path, यामध्ये filesystem media upload path देखील समाविष्ट आहे, त्याच्या आधारे सोडवते. After=postgresql.service केवळ सुरू करण्याचा आदेश देते; 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 मिळाल्यास process startup दरम्यान बंद झाला आहे; त्याचे कारण journalctl -u listmonk -n 50 --no-pager मध्ये नमूद असेल. लक्षात ठेवा, reboot नंतर टिकून राहणारा भाग enable --now आहे: हाताने सुरू केलेला process पुढील kernel upgrade नंतर बंद होतो.

nginx आणि TLS समोर ठेवणे

Listmonk loopback वर साधे 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 पेक्षा मोठ्या विनंत्या 413 Request Entity Too Large सह नाकारते. certbot वापरून प्रमाणपत्र जारी करा. ते तुमच्यासाठी listen 443 ssl ओळी आणि port 80 वरून redirect देखील लिहिते: पायऱ्या nginx साठी Let's Encrypt प्रमाणपत्र मार्गदर्शक येथे आहेत. ports 80 आणि 443 उघडे ठेवा आणि 9000 बंद ठेवा, कारण proxy त्याच्यापर्यंत loopback द्वारे पोहोचतो. Firewall अद्याप कॉन्फिगर केलेले नसल्यास, ufw firewall ची मूलभूत माहिती पासून सुरुवात करा.

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

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

config.toml मध्ये SMTP विभाग शोधा; तो तुम्हाला आढळणार नाही. मेलसंबंधी सेटिंग्ज डेटाबेसमधील settings सारणीत असतात. ती तुम्ही admin panel मधील Settings आणि SMTP अंतर्गत संपादित करता. त्यामुळे तयार होणारी फाइल इतकी लहान राहते. 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 provider हा port पूर्वनिर्धारितपणे block करतात. port 25 block असल्यास connection अडकलेली असल्यासारखीच दिसते, कारण packets नाकारण्याऐवजी drop केले जातात. त्यामुळे client त्वरित fail न होता timeout ची वाट पाहतो.

यावर विश्वास ठेवण्यापूर्वी चाचणी घ्या. एक list तयार करा. Subscriber म्हणून स्वतःचा address जोडा. त्यानंतर one-recipient campaign पाठवा. आलेला message उघडा आणि full headers वाचा. प्राप्त करणाऱ्या बाजूने जोडलेला Authentication-Results header SPF आणि DKIM पास झाले की नाही ते सांगतो.

वितरणक्षमतेचे काम पूर्णपणे महत्त्वाचे आहे

Listmonk संदेश तयार करते, यादीचा मागोवा घेते आणि ईमेल पुढे पाठवते. तो ईमेल इनबॉक्सपर्यंत पोहोचतो की नाही, याबाबतचा प्रत्येक निर्णय प्राप्त करणारा प्रदाता घेतो. तो यासाठी पाठवणारा IP address आणि पाठवणारे 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. पहिल्या दोन तपासण्या अयशस्वी झाल्यावर प्राप्तकर्त्यांनी काय करावे, हे तो सांगतो.
  • Listmonk वाचू शकेल असा bounce mailbox. त्यामुळे मेल नाकारणारे addresses यादीतून काढले जातात आणि त्यांच्यावर पुन्हा पुन्हा प्रयत्न होत नाहीत.

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

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

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

दोन गोष्टी सर्व्हरबाहेर ठेवणे आवश्यक आहे: डेटाबेस डंप आणि config.toml. मोहिमांमध्ये प्रतिमा अपलोड करत असल्यास मीडिया निर्देशिकाही समाविष्ट करा.

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

या डंपमध्ये सदस्य, मोहिमा, टेम्पलेट्स आणि SMTP क्रेडेन्शियल्ससह प्रत्येक सेटिंग साठवलेले असते. त्यामुळे ते एन्क्रिप्ट करा आणि या सर्व्हरबाहेर ठेवा. याचे वेळापत्रक ठरवणे ही सोडवलेली समस्या आहे: दूरस्थ स्टोरेजवर एन्क्रिप्ट केलेले restic बॅकअप पहा. config.toml मध्ये काही ओळी असतात, परंतु त्यात डेटाबेसचा पासवर्ड असतो. त्यामुळे त्याच पद्धतीने त्याचे संरक्षण करा.

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

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 करा आणि त्याच string ला file मध्ये ठेवा.

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

permission denied हे --install दरम्यान दिसल्यास role connect करू शकते, पण 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 मध्ये साठवल्या जातात. नवीन खात्यांवरील बहुतेक VPS providers बाहेर जाणारा port 25 block करतात. त्यामुळे STARTTLS सह port 587 किंवा implicit TLS सह port 465 वापरा.

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 हटवतो. --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 हा server कडून आलेला rejection Postgres driver पुढे पाठवत आहे. याचा अर्थ config file सापडली आणि वाचली गेली आहे. sudo -u postgres psql -c "ALTER USER listmonk WITH PASSWORD 'new-password';" वापरून role चा password reset करा. Config file मध्ये तोच string लिहा आणि नंतर sudo systemctl restart listmonk चालवा.