Kör en Zammad-helpdesk med Podman utan root

Zammad 7 på Debian 13, helpdesken med öppen källkod som gör e-post till din supportadress till ärenden, i rootless Podman under en egen användare bakom Caddy, som hämtar e-post via IMAP och svarar via din e-postleverantör.

Testad på Zammad 7.2.2 på Debian 13 (trixie) på en server hos Melonslab Uppdaterad 14 oktober 2026

Rekommenderad server för guiden

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy · 2 vCPU · 8 GB Minne · 60 GB Lagring

Månadsvis, ingen bindningstid 7 dagars öppet köp

100 kr/mån

Beställ nu
På den här sidan

Det här sätter du upp

Zammad är en helpdesk: varje mejl till din supportadress, till exempel support@example.com, blir ett ärende. Ditt team svarar i webbläsaren, kunden får svaret som ett vanligt mejl, och kundens svar hamnar i samma ärende. Ärenden kan tilldelas, taggas, slås ihop och sökas fram, och Zammad håller koll på hur snabbt ni svarar.

Zammad utvecklas av Zammad GmbH, ett företag i Berlin som också säljer Zammad som tjänst och support, och koden ägs av Zammad Foundation. Den är öppen källkod under licensen AGPL 3.0. När vi avlyssnade serverns trafik letade den inte efter uppdateringar och skickade inga användningsdata. Som standard använder den två externa tjänster som Zammad driver: den skickar e-postadressen för varje ny kund till images.zammad.com för att leta efter en profilbild, och adressen för varje inloggning till geo.zammad.com för att visa var den kom ifrån. Steg 8 stänger av båda. Under installationen frågar Zammad också geo.zammad.com var servern står, för att föreslå en kalender med helgdagar, och hämtar sedan helgdagarna från calendar.google.com en gång om dagen; steg 8 tar upp det också.

Zammad är ingen mailserver. Den hämtar e-posten till din supportadress från en brevlåda hos din e-postleverantör via IMAP, och skickar sina svar via samma leverantör över SMTP. Din e-post går alltså genom den leverantör du redan har.

Här körs Zammad som en pod med åtta containrar under en egen användare som heter zammad, bakom Caddy från Podman-guiden: PostgreSQL för data, Redis, Memcached, Elasticsearch för sökning, och Zammads webbserver, bakgrundsjobb, websocket-server och webbfront, med ett installationsjobb som körs före dem. Det är samma containrar som i Zammads officiella Docker Compose-uppsättning.

Varje steg nedan har körts på en nyinstallerad Melonslab VC-P Alloy (2 vCPU, 8 GB) med Debian 13:

  • Zammad 7.2.1 startade med PostgreSQL 17 och Elasticsearch 9.5.5, och administratörskontot skapades genom en SSH-tunnel innan Caddy sattes upp.
  • Ett mejl till supportadressen blev ett ärende, med ett automatiskt svar till kunden. En agents svar kom fram till kundens brevlåda, och kundens svar hamnade i samma ärende.
  • Zammad skickade e-post över SMTP med STARTTLS på port 587 och med TLS på port 465, båda mot testservrar för e-post på samma server. En avisering om ett nytt ärende och en återställning av lösenord kom fram.
  • Sökningen hittade ärenden på ett ord i texten. Gränssnittet visades på svenska.
  • Zammad loggade varje besökares riktiga adress, över IPv4 och IPv6, och struntade i en förfalskad X-Forwarded-For-header.
  • Med Zammads två tjänster avstängda gav ett ärende från en ny kund inga externa uppslagningar.
  • Zammad uppdaterades från 7.2.1 till 7.2.2 med podman auto-update. Den återställdes från en säkerhetskopia till tomma volymer, kördes utan Elasticsearch och startade igen av sig själv efter en omstart av servern.

Podden använde omkring 2,5 GB minne, varav 1,5 GB för Elasticsearch, så den får gott och väl plats på 8 GB. Elasticsearch är valfritt, men Zammads dokumentation rekommenderar det för sökningen, och Zammads rapporter kräver det. Utan det, som under Felsökning, använde podden omkring 800 MB, och sökningen hittade fortfarande ärenden på ord i texten.

Innan du börjar

Du behöver:

  • en server uppsatt som i Podman-guiden, med Caddy igång;
  • en A-post och en AAAA-post för help.example.com som pekar på din server;
  • en brevlåda för din supportadress hos din e-postleverantör, med åtkomst via IMAP och SMTP, och dess servernamn och lösenord. Har kontot tvåfaktorsautentisering ger leverantören oftast ett applösenord för det här.

Exemplen använder help.example.com för Zammad, support@example.com för supportadressen, mail.example.com för leverantörens mailserver och 203.0.113.10 för serverns IPv4-adress, som ip -brief address show eth0 visar. Byt ut dem genomgående.

1. Skapa användaren

Som root:

useradd -m -s /bin/bash zammad
loginctl enable-linger zammad
machinectl shell zammad@

Steg 2 och 3 körs som zammad.

2. Skapa hemligheten

openssl rand -hex 24 | tr -d '\n' | podman secret create zammad-db-password -

Det skapar databaslösenordet. Podman lagrar det, inte filerna nedan.

3. Definiera podden

mkdir -p ~/.config/containers/systemd
cd ~/.config/containers/systemd

Skapa zammad.pod:

[Pod]
PodName=zammad
# Only Caddy, on this server, can reach Zammad: the port is not open to the internet.
PublishPort=127.0.0.1:8147:8080

[Install]
WantedBy=default.target

Databasen, zammad-db.container:

[Container]
ContainerName=zammad-db
Image=docker.io/library/postgres:17-alpine
Pod=zammad.pod
Volume=zammad-db:/var/lib/postgresql/data
Environment=POSTGRES_USER=zammad POSTGRES_DB=zammad_production
Secret=zammad-db-password,type=env,target=POSTGRES_PASSWORD
HealthCmd=pg_isready -U zammad -d zammad_production
HealthInterval=10s
Notify=healthy
AutoUpdate=registry

[Service]
Restart=always

Redis, zammad-redis.container:

[Container]
ContainerName=zammad-redis
Image=docker.io/library/redis:8-alpine
Pod=zammad.pod
AutoUpdate=registry

[Service]
Restart=always

Memcached, zammad-memcached.container:

[Container]
ContainerName=zammad-memcached
Image=docker.io/library/memcached:1.6-alpine
Pod=zammad.pod
Exec=memcached -m 256M
AutoUpdate=registry

[Service]
Restart=always

Elasticsearch, zammad-search.container:

[Container]
ContainerName=zammad-search
Image=docker.io/library/elasticsearch:9.5.5
Pod=zammad.pod
Volume=zammad-search:/usr/share/elasticsearch/data
Environment=discovery.type=single-node xpack.security.enabled=false ingest.geoip.downloader.enabled=false
Environment="ES_JAVA_OPTS=-Xms1g -Xmx1g"

[Service]
Restart=always

Zammads installationsjobb, zammad-init.container, som skapar databasen vid första starten och uppdaterar den efter varje uppdatering:

[Unit]
Requires=zammad-db.service zammad-redis.service zammad-memcached.service zammad-search.service
After=zammad-db.service zammad-redis.service zammad-memcached.service zammad-search.service

[Container]
ContainerName=zammad-init
Image=ghcr.io/zammad/zammad:7.2
Pod=zammad.pod
Exec=zammad-init
EnvironmentFile=%h/zammad.env
Secret=zammad-db-password,type=env,target=POSTGRESQL_PASS
Volume=zammad-storage:/opt/zammad/storage

[Service]
Type=oneshot
TimeoutStartSec=15min

Själva Zammad körs som fyra containrar från samma avbild, som bara skiljer sig i namnet. Den här loopen skapar de fyra filerna, zammad-railsserver.container, zammad-scheduler.container, zammad-websocket.container och zammad-nginx.container:

for s in railsserver scheduler websocket nginx; do
cat > zammad-$s.container <<EOF
[Unit]
Wants=zammad-init.service
After=zammad-init.service

[Container]
ContainerName=zammad-$s
Image=ghcr.io/zammad/zammad:7.2
Pod=zammad.pod
Exec=zammad-$s
EnvironmentFile=%h/zammad.env
Secret=zammad-db-password,type=env,target=POSTGRESQL_PASS
Volume=zammad-storage:/opt/zammad/storage
AutoUpdate=registry

[Service]
Restart=always
EOF
done

Sist de inställningar som de delar, i ~/zammad.env:

ZAMMAD_FQDN=help.example.com
ZAMMAD_HTTP_TYPE=https
NGINX_SERVER_SCHEME=https
RAILS_TRUSTED_PROXIES=127.0.0.1,::1,203.0.113.10
TZ=Europe/Stockholm
POSTGRESQL_HOST=127.0.0.1
POSTGRESQL_DB_CREATE=false
REDIS_URL=redis://127.0.0.1:6379
MEMCACHE_SERVERS=127.0.0.1:11211
ELASTICSEARCH_HOST=127.0.0.1
ZAMMAD_RAILSSERVER_HOST=127.0.0.1
ZAMMAD_WEBSOCKET_HOST=127.0.0.1

Vad inställningarna gör:

  • ZAMMAD_FQDN och ZAMMAD_HTTP_TYPE ger Zammad dess publika adress, som den sätter i länkar och mejl. De läses bara vid första starten; senare finns adressen under Settings > System > Base i Zammad.
  • NGINX_SERVER_SCHEME=https talar om för Zammad att besökarna använder HTTPS, som Caddy sköter. Utan den misslyckas inloggningen med "CSRF token verification failed".
  • RAILS_TRUSTED_PROXIES listar de adresser som Zammad litar på när den får veta besökarens riktiga adress. Caddys anslutningar kommer in i podden från serverns egen IPv4-adress, som Podman-guiden förklarar, så det är den du lägger till.
  • Containrarna delar poddens nätverk, så de når varandra på 127.0.0.1, och bara webbfrontens port 8080 publiceras.
  • ghcr.io/zammad/zammad:7.2 följer varje patchversion av Zammad 7.2. PostgreSQL ligger kvar på 17 och Redis på 8. Elasticsearch har ingen tagg som följer en versionsserie, så dess version är låst; steg 10 förklarar hur du byter.
  • Elasticsearch får 1 GB för sina data, som i Zammads egen uppsättning. Den körs som en enda nod utan lösenord, eftersom bara podden når den, och laddar inte ner platsdatabaser från Elastic.

Starta den:

systemctl --user daemon-reload
systemctl --user start zammad-pod
systemctl --user enable --now podman-auto-update.timer

Vid första starten laddas omkring 3 GB avbilder ner, och sedan behöver installationsjobbet omkring fem minuter för att skapa databasen och sökindexet. Den är klar när det här skriver ut 200:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8147/

systemctl --user status zammad-init visar installationsjobbet. Det slutar som inactive (dead), och det är rätt: det körs och stannar sedan.

4. Skapa administratörskontot

Tills Zammad är uppsatt skapar den som öppnar den först administratörskontot. Därför ligger porten bara på 127.0.0.1, och därför når du den via SSH så länge. Från din egen dator:

ssh -L 8147:127.0.0.1:8147 root@203.0.113.10

Låt sessionen vara öppen och öppna http://localhost:8147 i webbläsaren. Zammad visar "This isn't the address Zammad is set up for", vilket stämmer eftersom den är uppsatt för help.example.com. Strunta i det.

  1. Välj Set up a new system.
  2. Ange ditt namn, din e-postadress och ett lösenord, och välj Create.
  3. Ange organisationens namn som Organization Name. System URL är redan https://help.example.com. Välj Next.
  4. Under Email Notification väljer du Skip, och under Connect Channels Skip igen. Steg 6 sätter upp e-posten.

Zammad öppnar sin översikt. Den tar tidszonen från din webbläsare; du kan kontrollera den under Settings > Branding > Timezone. Stäng SSH-sessionen.

5. Sätt Caddy framför

Gå tillbaka till root med exit, byt till machinectl shell caddy@ och lägg till det här blocket sist i ~/Caddyfile:

help.example.com {
    reverse_proxy 127.0.0.1:8147
}

Starta om Caddy med systemctl --user restart caddy, öppna https://help.example.com och logga in med kontot från steg 4.

Zammads inställningar finns under kugghjulet längst ner till vänster, i fyra delar: Manage, Channels, Settings och System. Stegen nedan nämner delen först.

6. E-post

E-posten är vägen in för ärendena och vägen ut för svaren. Zammad behöver två saker från din e-postleverantör: supportbrevlådan, som den läser via IMAP och skickar svar från via SMTP, och ett konto för att skicka sina egna aviseringar till teamet, till exempel om nya ärenden och återställda lösenord. Båda kan vara samma konto.

Zammad sparar de här lösenorden i sin databas, inte som hemligheter i Podman: du anger dem i dess inställningar, och de finns med i dina säkerhetskopior (steg 9).

Supportbrevlådan. Under Channels > Email väljer du New under Email Accounts. Ange namnet som kunderna ser som Organization & Department Name, till exempel Example Support, sedan adressen, dess lösenord och Users som Destination Group. Behåll Change to channel email address under Destination group > Sending email address, så skickar gruppen sina svar och automatiska svar från den här adressen. Välj Connect. För kända leverantörer hittar Zammad serverinställningarna själv. Annars frågar den efter dem:

  • Email Inbound: Type IMAP, leverantörens Host, till exempel mail.example.com, hela adressen som User, SSL/STARTTLS SSL och Port 993.
  • Keep Messages on Server: med no raderar Zammad varje mejl från brevlådan när det har blivit ett ärende. Välj yes för att behålla det där; Zammad markerar det då som läst.
  • Email Outbound: samma Host och User, och Port 587, som använder STARTTLS, eller 465, som använder TLS från början.

Välj Continue. Zammad skickar ett testmejl till brevlådan och väntar på att det kommer tillbaka innan kontot sparas, vilket tar upp till en minut. Sedan hämtar den ny e-post ungefär var 30:e sekund.

Aviseringar. På samma sida, under Email Notification, väljer du Edit bredvid Outbound, anger leverantörens SMTP-uppgifter Host, User, Password och Port 587, och väljer Continue. När du sparar skickar Zammad ett testmejl till verify-external-smtp-sending@discard.zammad.org, en adress hos Zammad som slänger det. Sätt sedan, under fliken Settings, Notification Sender till en adress som kontot får skicka från, till exempel Example Helpdesk <support@example.com>, och välj Submit. Zammads standard, noreply@help.example.com, är ingen adress som din leverantör skickar för.

Signatur. Varje svar får signaturen under fliken Signatures, och den som Zammad levereras med är ett exempel, med en adress i Miami. Öppna default, skriv er egen och välj Submit.

För Gmail och Microsoft 365 finns Google Email och Microsoft 365 Graph Email under Channels, som ansluter med leverantörens egen inloggning i stället för ett lösenord. Vi har inte testat dem.

Utan e-post:

  • kommer inga ärenden in via e-post, och ett svar på ett ärende kan bara vara en intern anteckning;
  • visar en inbjudan av en kollega under First Steps i översikten "Can't create user!" med ett SMTP-fel, trots att kontot skapas;
  • säger Forgot password? att instruktionerna har skickats, men inget kommer fram.

Ärenden som skapas i webbläsaren, och inloggning med lösenord, fungerar som vanligt.

7. Agenter och kunder

Agenter svarar på ärenden. Lägg till dem under Manage > Users > New User: markera Agent under Roles och full för de grupper de arbetar i under Group Permissions. Zammad skickar inget mejl till dem; sätt ett Password åt dem, eller låt dem använda Forgot password? på inloggningssidan.

Kunder är de som skriver till er. Varje ny adress som mejlar supportadressen får ett kundkonto av sig självt. Som standard kan kunder också logga in på https://help.example.com för att se sina ärenden och skapa nya: Register as a new customer på inloggningssidan låter vem som helst skapa ett konto, och Forgot password? låter alla som har skrivit till er sätta ett lösenord. Vill du bara ta emot ärenden via e-post sätter du New User Accounts till no under Settings > Security > Base. Fliken Two-factor Authentication bredvid slår på tvåfaktorsinloggning.

För att svara på ett ärende öppnar du det från Overviews, väljer svarspilen under kundens meddelande, skriver och väljer Update. Låsikonen gör svaret till en intern anteckning som bara teamet ser. Sökrutan högst upp hittar ärenden på vilket ord som helst i dem.

8. Svenska och externa tjänster

Zammad är översatt till svenska. Varje användare väljer Svenska under sin avatar > Profile > Language. För att göra svenska till standard för alla som inte har valt något språk väljer du det under Settings > Branding > Locale och väljer Submit. Inloggningssidan följer språket i besökarens webbläsare.

Zammad skapar också en kalender med arbetstider och helgdagar, som eskaleringstider och SLA:er räknas i. Den frågar Zammads platstjänst var servern står, och på vår server blev det en kalender som hette France, med fransk tid och franska helgdagar. Under Manage > Calendars väljer du Edit, sätter Name till Sweden, Time Zone till Europe/Stockholm och Subscribe to public holidays in till Sweden, eller ditt eget land, och väljer Submit. Zammad hämtar sedan helgdagarna från calendar.google.com en gång om dagen. Den svenska listan har med dagar som du förmodligen arbetar, som Valentine's Day och Walpurgis Night: bocka ur dem under Holidays.

Under Settings > System > Services sätter du Image Service och Geo IP Service till - och väljer Submit för var och en:

  • Image Service skickar e-postadressen för varje ny kund till images.zammad.com för att hämta en profilbild. I vår avlyssning gav ett ärende från en ny adress en uppslagning av images.zammad.com; med tjänsten avstängd blev det inga uppslagningar alls.
  • Geo IP Service skickar IP-adressen för varje inloggning till geo.zammad.com, för att visa var den kom ifrån under System > Sessions.

Geo Location Service slår upp gatuadresser som du anger för användare hos OpenStreetMap. Geo Calendar Service är den som frågade geo.zammad.com var servern står under installationen; Zammad använder den inte efter det. Båda kan du också sätta till -.

9. Säkerhetskopiera

Som zammad:

umask 077
mkdir -p ~/backup
podman exec zammad-db pg_dump -U zammad zammad_production > ~/backup/zammad-db.sql
podman volume export zammad-storage > ~/backup/zammad-storage.tar

Ärendena, deras bilagor, användare och inställningar, med lösenorden för e-posten, ligger i databasen. Volymen zammad-storage innehåller bara bilagor om du sätter Storage Method till Filesystem under Settings > System > Storage. Sökindexet behövs inte: Zammad bygger det igen från databasen. Dumpen körs medan Zammad fortsätter att fungera. Kopiera ~/backup till en annan maskin, till exempel med restic, och förvara den säkert.

För att återställa till en tom pod, som zammad, med säkerhetskopian i ~/backup:

systemctl --user stop zammad-pod
podman volume rm zammad-db zammad-storage zammad-search
podman volume create zammad-storage
podman volume import zammad-storage ~/backup/zammad-storage.tar
systemctl --user start zammad-db
podman exec -i zammad-db psql -q -o /dev/null -U zammad zammad_production < ~/backup/zammad-db.sql
systemctl --user start zammad-pod

Genom att bara starta databasen först läses säkerhetskopian in innan installationsjobbet körs. Installationsjobbet hittar sedan en befintlig databas och bygger sökindexet igen, och Zammad svarar efter omkring tre minuter.

10. Uppdatera

podman auto-update letar en gång om dagen efter nya avbilder av Zammad 7.2, PostgreSQL 17, Redis 8 och Memcached. När någon har ändrats startar den om hela podden, och installationsjobbet uppdaterar databasen innan Zammad startar. För att uppdatera direkt:

podman auto-update

Zammad är otillgänglig i tre eller fyra minuter medan den startar om. För en ny mindre version, som 7.3, läser du versionsinformationen, gör en säkerhetskopia och byter taggen i de fem filer som använder den:

sed -i 's|zammad/zammad:7.2|zammad/zammad:7.3|' ~/.config/containers/systemd/zammad-*.container
systemctl --user daemon-reload
systemctl --user restart zammad-pod

För att flytta Elasticsearch till en nyare version byter du dess tagg i zammad-search.container till den i Zammads egen Docker Compose-fil, kör sedan daemon-reload och startar om podden. Vi har bara testat uppdateringen inom 7.2.

Felsökning

curl skriver ut 000 eller 502 långt efter starten. Installationsjobbet är inte klart, eller har misslyckats. journalctl --user -u zammad-init visar hur långt det har kommit. Vid första starten tar det flera minuter.

Inloggningen misslyckas med "CSRF token verification failed". NGINX_SERVER_SCHEME=https saknas i ~/zammad.env. Lägg till den och starta om podden med systemctl --user restart zammad-pod.

Zammad loggar varje besökare med serverns egen adress. RAILS_TRUSTED_PROXIES saknar serverns IPv4-adress. Rätta den i ~/zammad.env och starta om podden. Loggen visas med podman logs zammad-railsserver.

Ingen e-post hämtas. Channels > Email visar felet från senaste hämtningen bredvid kontot. Kontrollera lösenordet, och att IMAP är påslaget för brevlådan hos leverantören.

Kunderna får inget automatiskt svar. podman logs zammad-scheduler säger "no email address is set for group 'Users'". Under Manage > Groups öppnar du Users, väljer supportadressen som Sending Email Address och väljer Submit. Det händer när brevlådan sattes upp med Do not change email address, eller via Zammads API.

Kör utan Elasticsearch. På en server med 4 GB hoppar du över den. Som zammad:

cd ~/.config/containers/systemd
sed -i 's/ zammad-search.service//' zammad-init.container
rm zammad-search.container
echo ELASTICSEARCH_ENABLED=false >> ~/zammad.env
systemctl --user daemon-reload
systemctl --user stop zammad-pod
systemctl --user start zammad-pod

Zammad söker då i sin databas i stället. podman volume rm zammad-search frigör diskutrymmet för det gamla indexet, och återställningen i steg 9 hoppar då över zammad-search.

Kör det på din egen server

SSD RAID 1 · ECC DDR4 · 10 Gbit

VC-P Alloy

100 kr/mån

vCPU
2
Minne
8 GB
Lagring
60 GB
Trafik
10 TB
Performance
SSD · RAID 1
  • Full root-åtkomst
  • Nativt /64 IPv6
  • RAID-skyddad lagring
  • Malmö, Sverige
  • Månadsvis, ingen bindningstid
  • 7 dagars öppet köp
Alla guider