A newsletter you run on your own server

Docs

Install with Docker

Run Mailpiece as one ready-made container. There's nothing to build on the server.

Paste this into your agent

Install Mailpiece on my server with Docker. Read mailpiece.dev/llms.txt first.

What you need

The image is ghcr.io/mailpiece/mailpiece:main, built from main on each change, with web and jobs together. The server needs Docker and what What you need lists there.

To change the code and deploy it from your computer, install with Kamal instead.

Make the secret key

Make it once and keep it safe apart from the server: the relay token and SMTP password Mailpiece stores are encrypted with keys derived from it. A new one also signs everyone out, and the rating links in issues already mailed stop answering.

openssl rand -hex 64      # SECRET_KEY_BASE

Run it

Mount a named volume at /rails/storage, or the databases, uploads and certificate are lost with the container. One container runs web and jobs; the database is created on first start. The settings are explained in Configuration.

Then open /signup and create the first account, as in Open it.

docker run -d --name mailpiece --restart unless-stopped \
  --publish 80:80 --publish 443:443 \
  --volume mailpiece:/rails/storage \
  --env SECRET_KEY_BASE=... \
  --env TLS_DOMAIN=app.example.com \
  --env BASE_URL=https://app.example.com \
  --env "MAILER_FROM_ADDRESS=My Newsletter <[email protected]>" \
  --env SMTP_ADDRESS=smtp.example.com \
  --env SMTP_USERNAME=... \
  --env SMTP_PASSWORD=... \
  ghcr.io/mailpiece/mailpiece:main

With docker compose

The same container. Start it with docker compose up -d.

services:
  web:
    image: ghcr.io/mailpiece/mailpiece:main
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    environment:
      - SECRET_KEY_BASE=...
      - TLS_DOMAIN=app.example.com
      - BASE_URL=https://app.example.com
      - MAILER_FROM_ADDRESS=My Newsletter <[email protected]>
      - SMTP_ADDRESS=smtp.example.com
      - SMTP_USERNAME=...
      - SMTP_PASSWORD=...
    volumes:
      - mailpiece:/rails/storage

volumes:
  mailpiece:

Update it

Mailpiece stops while the new container boots.

docker pull ghcr.io/mailpiece/mailpiece:main
docker stop mailpiece && docker rm mailpiece
# then the same docker run as above

# Under compose
docker compose pull && docker compose up -d

On a laptop

Leave TLS_DOMAIN out, publish port 80 only and set DISABLE_SSL=true to reach Mailpiece over plain HTTP. Plain HTTP is for trying Mailpiece on your own machine.

Behind a proxy that handles HTTPS, leave TLS_DOMAIN out and publish port 80 only, without DISABLE_SSL.

# On a laptop
docker run ... --publish 80:80 --env DISABLE_SSL=true --env BASE_URL=http://localhost ...

# Behind a proxy that handles HTTPS
docker run ... --publish 80:80 ...

Then

Take your first steps.

Still need help? Ask on GitHub.