Skip to main content
50% rabat alle planer, tidsbegrænset. Fra $2.48/mo
14 min. tilbage
Web- og forretningsapps

Sådan self-hoster du dit nyhedsbrev med Listmonk

C By Chike 14 min. læsning
Sådan self-hoster du dit nyhedsbrev med Listmonk på en VPS: Docker Compose, SMTP-relay og SPF/DKIM/DMARC-leverbarhed.

Når du self-hoster, kører Listmonk på en VPS, du allerede betaler for. Afsendelsen koster det, dit SMTP-relay tager pr. tusind e-mails. Antallet af abonnenter ændrer ingen af de to tal. Det er det strukturelle skifte, der gør self-hosting besværet værd, når du vokser ud af et gratis managed-niveau.

Listmonk er en open source-nyhedsbrevsmanager skrevet i Go. Du får ubegrænsede abonnenter, lister og kampagner for prisen på en VPS plus en SMTP-relay-konto. Én ting skal stå klart, før du rører en kommando: Listmonk håndterer alt undtagen selve afsendelsen. Om din e-mail lander i indbakken eller spammappen afgøres af det SMTP-relay, du konfigurerer, og de DNS-records, du opsætter på dit afsenderdomæne.

Hvad denne guide dækker

  • Deploy Listmonk og PostgreSQL med Docker Compose bag en Nginx- (eller Caddy-) reverse proxy med HTTPS
  • Vælg det rigtige SMTP-relay til dit volumen og budget (Amazon SES, Postmark, Brevo eller et andet)
  • Konfigurér SPF, DKIM og DMARC på dit afsenderdomæne
  • Undgå fire produktionsfejl, der ofte ikke giver tydelige fejlbeskeder
  • Anslået tid: 30 minutter, hvis du har en VPS og et domæne klar
  • Uden for emnet: drip-automatisering, transaktionsmails, opsætninger med flere instanser (se FAQ)

Når Listmonk er det forkerte værktøj

Listmonk er det rigtige svar i en bestemt situation. Hvis din situation er anderledes, findes der et bedre svar.

Volumen under ~10K e-mails om måneden. Gratis managed-niveauer hos Brevo eller Mailchimp kan koste mindre alt-i-alt end en VPS plus et SMTP-relay i denne størrelse. Self-hosting begynder at betale sig, når du krydser det interval. Tjek tallene mod dit faktiske abonnentantal og din afsendelsesfrekvens, før du deployer.

Ikke-teknisk team. Mailchimp og Brevo har reelt bedre brugerflader til folk, der ikke arbejder i en terminal. Listmonk forudsætter, at nogen på teamet kan SSH'e ind på en server, læse Docker-logs og tolke DNS-propagering. Findes den person ikke, er managed-tjenester det rigtige valg.

Brug for automatiseringsflows. Listmonk sender kampagner. Det understøtter ikke drip-sekvenser, adfærdsudløste e-mails eller visuelle flow-byggere. Har du brug for det, så kør Mautic eller koble Listmonk til n8n for automatiseringslaget.

GDPR-følsomme abonnentlister. Hvis dine abonnenter primært er i EU, eller din liste er underlagt GDPR-regler om dataopbevaring, så kør Listmonk i et europæisk datacenter. Vi tilbyder placeringer i Frankfurt og London, der opfylder EU-kravene til dataopbevaring.

Hvad du har brug for, før du går i gang

Listmonk plus PostgreSQL plus en moderat kø-arbejdsbyrde kræver mindst 2 GB RAM. 4 GB er det komfortable mål til produktion.

Hardware. Til en personlig liste under 50K e-mails om måneden er en VPS med 2 vCPU, 4 GB RAM og 120 GB NVMe-lagring tilstrækkelig. Voksende lister på 200K+ om måneden kræver 4 vCPU og 8 GB RAM. Vi kører denne Compose-opsætning på en 4 GB VPS i Frankfurt. Vælg en placering tæt på dine abonnenter, hvis du kan. Afsendelsesforsinkelse betyder ikke meget; det gør responstiden i admin-panelet derimod.

Domæne. Et domæne, der peger på din VPS via en A-record. Brug et subdomæne til admin-grænsefladen, for eksempel mail.example.com. Afsenderdomæne og admin-subdomæne kan være det samme rod-domæne.

SMTP-relay-konto. Opret ikke en endnu. Valget af relay er den mest betydningsfulde beslutning i denne guide, og det afhænger af dit volumen. Spring frem til afsnittet "Valg af dit SMTP-relay", vælg en udbyder, og kom så tilbage hertil med SMTP-host, port, brugernavn og adgangskode i hånden.

Software på din VPS. Ubuntu 22.04 LTS eller 24.04 LTS. Docker Engine 24.0 eller nyere med Docker Compose-pluginet. UFW eller en tilsvarende firewall med portene 22, 80 og 443 åbne. SSH-adgang som en non-root sudo-bruger.

Deploy Listmonk med Docker Compose

Listmonk og PostgreSQL deployet med Docker Compose på en VPS, bag en Nginx- eller Caddy-reverse proxy, der terminerer HTTPS.

Opret en mappe til deployment'et, og læg så en docker-compose.yml fil med to services: postgres til databasen og listmonk til applikationen. Begge genstarter ved fejl. Listmonk binder til 127.0.0.1 så reverse proxy'en er det eneste, der kan nå den.

Docker Compose-filen

I'd be happy to help translate to Danish, but the text you've provided appears to be incomplete. You've only written "Here is the" without the rest of the content. Could you please provide the full text you'd like me to translate? docker-compose.yml. Verificér de præcise image-tags og navne på miljøvariabler mod den officielle Listmonk-installationsdokumentation. De opdateres ved hver udgivelse.

# docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    container_name: listmonk-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: listmonk
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: listmonk
    volumes:
      - listmonk-postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U listmonk"]
      interval: 10s
      timeout: 5s
      retries: 6

  app:
    image: listmonk/listmonk:latest
    container_name: listmonk-app
    restart: unless-stopped
    # Bind to loopback only. The reverse proxy is the public entrypoint.
    ports:
      - "127.0.0.1:9000:9000"
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      LISTMONK_app__address: "0.0.0.0:9000"
      LISTMONK_db__host: postgres
      LISTMONK_db__port: 5432
      LISTMONK_db__user: listmonk
      LISTMONK_db__password: ${POSTGRES_PASSWORD}
      LISTMONK_db__database: listmonk

volumes:
  listmonk-postgres:

Opret en .env fil med POSTGRES_PASSWORD= sat til en lang tilfældig streng. Start så stakken, og kør den engangsdatabase-installation:

# Pull images and start the database first
docker compose up -d postgres

# Run the install step (creates schema and the first admin user)
docker compose run --rm app ./listmonk --install --idempotent --yes

# Start the application
docker compose up -d

Den --install kommandoen beder om en admin-e-mail og adgangskode. Gem dem. Verificér, at begge containere kører:

docker compose ps

Forventet output: to services listet, begge med status Up. Postgres-rækken bør vise (healthy).

Den 127.0.0.1:9000 binding er bevidst. Listmonk har ingen indbygget rate-limiter til godkendelse og ingen IP-allowlisting. At eksponere port 9000 mod det offentlige internet betyder, at hvem som helst på kloden kan ramme dit admin-login. Reverse proxy'en er det, der gør det login tilgængeligt udelukkende over HTTPS.

Nginx-reverse proxy og SSL

Installér Nginx og Certbot fra Ubuntu-repositories. Opret en site-konfiguration på /etc/nginx/sites-available/listmonk med de proxy-headers, Listmonk har brug for til at generere korrekte kampagnelinks:

# /etc/nginx/sites-available/listmonk
server {
    listen 80;
    server_name mail.example.com;

    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;

        # Listmonk streams campaign progress over WebSocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

Lav et symlink ind i sites-enabled, test konfigurationen, genindlæs Nginx, og udsted så et certifikat:

sudo ln -s /etc/nginx/sites-available/listmonk /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d mail.example.com

Certbot omskriver server-blokken, så den lytter på 443 med det nye certifikat, og tilføjer en HTTP-til-HTTPS-omdirigering. Verificér:

curl -I https://mail.example.com

Forventet output: HTTP/2 200 med en gyldig strict-transport-security-header. Får du et redirect-loop, så tjek, at X-Forwarded-Proto headeren er sat i Nginx-konfigurationen ovenfor. Ni ud af ti gange er loopet netop den header.

Hvis Listmonk er det eneste på denne VPS, så brug Caddy i stedet. Caddyfile'en er tre linjer, og den håndterer certifikatfornyelse uden et cronjob:

mail.example.com {
    reverse_proxy 127.0.0.1:9000
}

Ret Message-ID-headeren

Som standard bruger Listmonk systemets hostname i den udgående Message-ID-header. Hvis din VPS-hostname er localhost eller noget, der ikke er et gyldigt FQDN, sender Listmonk Message-ID: <[email protected]>. Spamfiltre hos Gmail og Outlook flagger det med det samme. Det er dokumenteret i Cloudron Forum-tråd 15410.

Løsningen er én linje i Listmonks config.toml. For en frisk installation genereres filen via docker compose run --rm app ./listmonk --new-config. Sæt så:

[app]
hostname = "mail.example.com"

Genstart app-containeren efter redigeringen:

docker compose restart app

Gør det, før du sender en eneste kampagne. En liste forurenet med localhost.localdomain Message-ID'er er sværere at rette op på end en, der startede rent.

Professionelt råd

Hvis du hellere vil springe Compose-opsætningen over, så tjek vores one-click Listmonk VPS for at deploye Listmonk på få minutter med ét klik. Instansen leveres færdigkonfigureret med PostgreSQL. Du skal stadig konfigurere dit SMTP-relay og tilføje dine DNS-records. De trin er ikke valgfrie, uanset hvordan du deployer.

Valg af dit SMTP-relay

Valg af et SMTP-relay til Listmonk: Amazon SES, Postmark, Brevo og Mailgun sammenlignet på prisstruktur, bounce-webhooks og bedste pasform.

Al afsendelse sker gennem et relay, du konfigurerer. Relayets IP-omdømme, rate limits og bounce-håndtering er det, der afgør, om din e-mail lander i indbakken eller spammappen.

Her er den funktionelle sammenligning. Priser og grænser for gratis niveauer ændrer sig. Verificér hver enkelt på udbyderens officielle prisside, før du forpligter dig.

LeverandørPrisstrukturBounce-webhooksBedst til
Amazon SESPr. e-mail, meget lav ved volumenJa, via SNSPris ved volumen; allerede på AWS
PostmarkMånedlig basis plus pr. e-mailJa, indbyggetLeverbarhed først; omdømme til transaktionsmails
BrevoGratis niveau til lavt volumen, betalte niveauer deroverJaLavt volumen med opgraderingssti
MailgunPris pr. e-mailIntet indbygget webhook-endpoint; brug det generiske bounce-API om nødvendigt.Velkendt for udviklere

Det var bare et hurtigt kig på hvert SMTP-relay. Nu gennemgår vi hvert af dem i dybden.

SES er den billigste mulighed ved volumen og den mest omtalte i Listmonk-fællesskabet. Opsætningen har flere trin end Postmark eller Brevo, men forskellen i pris pr. e-mail er stor nok ved ethvert reelt volumen til at retfærdiggøre arbejdet.

Sæt det op i tre faser. Først opretter du en IAM-bruger med AmazonSESFullAccess politikken (eller en strammere brugerdefineret politik med kun ses:SendRawEmail og ses:GetSendQuota). Dernæst verificerer du dit afsenderdomæne i SES-konsollen. SES guider dig gennem de DKIM-CNAME'er, du skal tilføje. Til sidst genererer du SMTP-credentials fra SES SMTP-indstillingspanelet. Det er ikke dine AWS-adgangsnøgler; SES genererer et separat SMTP-specifikt brugernavn og en adgangskode, når du klikker "Create SMTP credentials."

I Listmonks admin under Settings → SMTP tilføjer du en ny server med:

  • Vært: email-smtp.<region>.amazonaws.com (brug den SES-region, du verificerede domænet i)
  • Port: 587
  • Auth-protokol: LOGIN
  • TLS: STARTTLS
  • Brugernavn og adgangskode: de SMTP-credentials, SES genererede

SES kræver STARTTLS på port 587. Hvis du lader TLS stå på none eller vælger port 465, forbinder Listmonk, SES returnerer 530 Must issue a STARTTLS command first, og SMTP-credential-testen i admin-panelet kan stadig vise succes. Send en rigtig test-e-mail til en personlig indbakke, du har kontrol over, før du kører nogen kampagne.

Nye SES-konti starter i sandkasse-tilstand. I sandkassen kan du kun sende til verificerede e-mailadresser, hvilket ikke er brugbart til en abonnentliste. Åbn en support-sag fra SES-konsollen for at anmode om produktionsadgang. Godkendelse tager typisk én arbejdsdag.

Postmark (leverbarhed først-alternativ)

Postmark koster mere pr. e-mail end SES, men har indbygget understøttelse af bounce-webhooks og et omdømme for høje indbakkerater med strenge afsenderpolitikker. Det er det værd, hvis dine nyhedsbreve er forretningskritiske, eller du ikke vil håndtere SES' godkendelse fra sandkasse til produktion.

Listmonk-konfigurationen har samme form som SES: host, port 587, STARTTLS, credentials fra API-token-panelet på Postmark-serveren. Verificér dit afsenderdomæne i Postmarks signatur-opsætning, tilføj de DKIM-records, Postmark genererer, og du er klar til at sende.

Vælg Postmark, når leverbarhed betyder mere end prisen pr. e-mail. Vælg SES, når volumen betyder mere end ekstra håndholdning.

En advarsel om SMTP-credential-testen. Forbindelsestesten i Listmonks admin rapporterer altid succes, selv med ugyldige credentials. Det er dokumenteret i et par GitHub-issues. Stol ikke på den. Efter at have konfigureret et hvilket som helst relay, så send en kampagne til en enkelt test-abonnent og bekræft modtagelsen i mål-indbakken, før du sender til hele din liste.

Undgå Mailersend til afsendelse af bulk-kampagner. Dets grænse på 5 e-mails pr. forbindelse producerer 421 Service not available fejl, som Listmonk registrerer som sendt, selvom leveringen mislykkedes. Kampagnen ser vellykket ud i Listmonk og taber de fleste af sine beskeder uden varsel.

Sådan får du e-mail til reelt at lande: SPF, DKIM og DMARC

SPF-, DKIM- og DMARC-DNS-records på afsenderdomænet, der lader modtagende mailservere verificere Listmonks e-mail og holde den ude af spam.

Det er tre DNS-records på dit afsenderdomæne, der fortæller modtagende mailservere, at dit domæne har autoriseret dette relay til at sende på dine vegne. Springer du blot én af dem over, rammer en betydelig andel af dine afsendelser spam i stor skala, uanset hvor rent dit relay eller din tekst er. Tilføj dem hos din DNS-udbyder, før du sender den første kampagne.

SPF-record

SPF autoriserer bestemte IP'er eller afsendertjenester til at sende e-mail for dit domæne. Tilføj en enkelt TXT-record ved roden af dit afsenderdomæne med include for dit relay. For SES ser recorden sådan ud:

v=spf1 include:amazonses.com ~all

For Postmark erstattes include med include:spf.mtasv.net. Tjek altid dit relays officielle SPF-dokumentation for den præcise include-værdi. Den ændrer sig efter udbyder og nogle gange efter region.

Et domæne kan kun have én SPF-record. Har du allerede en til en anden tjeneste (Google Workspace, Microsoft 365), så flet include ind i den eksisterende record i stedet for at tilføje endnu en.

DKIM

DKIM knytter en kryptografisk signatur til udgående e-mails, som modtagende servere verificerer mod en offentlig nøgle i din DNS. Dit relay genererer nøgleparret. Du tilføjer den offentlige nøgle som en TXT-record på et selector-subdomæne (for eksempel sel1._domainkey.example.com) med den præcise værdi, relayet giver dig.

Listmonk håndterer ikke DKIM-signering. Det gør relayet. Der er ingen Listmonk-specifik DKIM-konfiguration. Følg dit relays DKIM-opsætningsguide, tilføj de records, den giver dig, og vent på DNS-propagering (normalt under 30 minutter; nogle gange et par timer).

DMARC

DMARC fortæller modtagende servere, hvad de skal gøre med e-mail, der fejler SPF- eller DKIM-tjek. Start i overvågningstilstand med p=none så du kan se fejl i de samlede rapporter uden at påvirke leverbarheden, mens du retter fejlkonfigurationer. Tilføj en TXT-record på _dmarc.example.com:

v=DMARC1; p=none; rua=mailto:[email protected]

Efter to-tre uger med rene rapporter strammer du politikken til p=quarantine or p=reject. Spring ikke overvågningsfasen over. En tastefejl i din SPF-include kombineret med p=reject på dag ét vil udradere din egen legitime e-mail uden noget signal om, at noget gik galt.

List-Unsubscribe-headeren (RFC 8058) genereres automatisk af Listmonk. Bekræft, at den er aktiveret under Settings → General. Gmail og Apple Mail viser denne header som en ét-kliks afmeldingsmulighed, hvilket beskytter afsenderens omdømme.

Hvad der reelt går galt i produktion

Fire fejltilstande, der ikke dukker op, før du sender din første rigtige kampagne. Fang dem, før dine abonnenter gør.

Problem 1: Bounce-raten matcher ikke dit relays tal. Listmonk behandler bounces ved at læse en udpeget bounce-e-mailadresse over POP3 og slette hver besked, den læser. Det inkluderer feriesvar, leveringskvitteringer og fraværsbeskeder, alle klassificeret som bounces. Dit relay tæller kun reelle leveringsfejl returneret af modtagernes mailservere. Hvis SES rapporterer 0,6% og Listmonk rapporterer 4%, er det her, forskellen er. Løsningen er at konfigurere bounce-webhook-callbacks i stedet for POP3. For SES bruger du SNS til at levere bounce-notifikationer til Listmonks webhook-endpoint. For Postmark peger du dens indbyggede webhook på det samme endpoint. Webhook-bounces er nøjagtige; POP3-bounces oppuster tallene.

Problem 2: SMTP-credential-testen siger succes, når den tager fejl. Som nævnt i relay-afsnittet rapporterer forbindelsestesten altid succes uanset gyldigheden af credentials. Stol ikke på den. Send altid en rigtig test-e-mail efter at have konfigureret eller ændret en hvilken som helst SMTP-indstilling.

Problem 3: En kampagne stopper midt i afsendelsen uden fejl. Listmonk markerer kampagner som Finished, selv når kun 60% af abonnenterne modtog e-mailen. De resterende afsendelser blev afvist af relayet eller struben i VPS'ens netværkslag, og Listmonk viser ingen af delene som en fejl på kampagneniveau (Cloudron Forum-tråd 13165). Hvis en kampagne viser færre afsendelser end abonnenter, så åbn dit relays dashboard for afsendelsens tidsvindue og sammenlign relayets accepterede antal mod Listmonks. Sandheden er i relayet.

Problem 4: Ingen tager backup af PostgreSQL. Compose-volumet bevarer data på tværs af genstarter. Det beskytter ikke mod værtsfejl, et utilsigtet docker volume rm eller korrupte opgraderinger. Tilføj en daglig pg_dump:

0 2 * * * docker exec listmonk-postgres pg_dump -U listmonk listmonk > /backups/listmonk-$(date +\%Y\%m\%d).sql

Kør linjen én gang i hånden først. Verificér, at outputfilen ikke er tom, før du stoler på cron-indgangen. Et backup-script, der skriver en nul-byte-fil uden at rejse en fejl, er værre end ingen backup overhovedet, fordi du holder op med at tænke på det.

Før du stoler på noget af dette i produktion, så send en testkampagne til én abonnent og bekræft modtagelsen i mål-indbakken. Lander den ene e-mail rent, gør de næste ti tusind det også.

Ofte stillede spørgsmål

Hvorfor er mine Listmonk-bounce-rater højere end det, Amazon SES rapporterer?

Listmonks POP3-bounce-behandling oppuster tallene ved at læse fraværssvar og ferie-autosvar som bounces. Konfigurér SES SNS-webhook-callbacks for nøjagtige tal.

Understøtter Listmonk transaktionsmails?

Listmonk er et værktøj til nyhedsbreve og broadcast-kampagner. Det håndterer ikke indbygget transaktionsmails (nulstilling af adgangskode, ordrebekræftelser, en-til-en-udløste e-mails). For transaktionsmails fra samme afsenderdomæne konfigurerer du dit relays transaktions-endpoint separat eller bruger et dedikeret værktøj som Postal eller Postmarks transaktions-API ved siden af Listmonk.

Hvordan importerer jeg mine Mailchimp-abonnenter ind i Listmonk?

Eksportér din Mailchimp-liste som en CSV fra Audience → Export Audience. I Listmonk går du til Subscribers → Import og uploader CSV-filen. Mapp e-mail- og navnekolonnerne, når du bliver bedt om det. Listmonk accepterer standard-CSV-eksporter fra Mailchimp, ConvertKit og de fleste nyhedsbrevsplatforme uden formatkonvertering.

Hvad sker der, når nogen afmelder sig en Listmonk-kampagne?

Listmonk tilføjer som standard et afmeldingslink til hver kampagne-e-mail. Når en abonnent klikker på det, føjes vedkommende til blokeringslisten og fjernes fra alle fremtidige kampagner. List-Unsubscribe-headeren (RFC 8058) inkluderes automatisk, så mailklienter, der understøtter ét-kliks afmelding (Gmail, Apple Mail), viser den indbygget. Abonnentposten forbliver i databasen til revisionsformål, men der sendes ingen yderligere kampagner til dem.

Del

Mere fra bloggen

Læs videre.

Klar til at udrulle? Fra 2,48 $/md.

Uafhængig cloud siden 2008. AMD EPYC, NVMe, 40 Gbps. 14 dages pengene-tilbage-garanti.