Installation
This document describes how to deploy a production Patchwork instance. Patchwork 4.0 is a single Go binary that replaces the previous Django/Python deployment.
Requirements
Patchwork requires:
The
pwbinary (built from source or downloaded from a release)A supported database: PostgreSQL (recommended), MySQL/MariaDB, or SQLite
A mail transfer agent (e.g. Postfix) for receiving patches
A reverse proxy (e.g. nginx) for TLS termination (optional but recommended)
Building from source requires Go 1.22 or later:
$ git clone https://github.com/getpatchwork/patchwork.git
$ cd patchwork
$ make
$ sudo make install
Database Setup
PostgreSQL (Recommended)
Install PostgreSQL and create a database:
$ sudo apt-get install -y postgresql
$ sudo -u postgres createuser -d patchwork
$ sudo -u postgres createdb -O patchwork patchwork
SQLite
No setup is needed. Simply point the configuration at a file path:
[database]
url = "sqlite:///var/lib/patchwork/patchwork.db"
Note
SQLite is suitable for small installations and development. For production use with multiple concurrent users, PostgreSQL is recommended.
Configuration
Generate a default configuration file:
$ pw config > /etc/patchwork.toml
Edit /etc/patchwork.toml to set at least the database URL and the HTTP base
URL. See Configuration for a full reference of all available settings.
A minimal configuration looks like:
[database]
url = "postgres://patchwork:secret@localhost/patchwork"
auto-sync = true
[http]
listen = "127.0.0.1:8080"
base-url = "https://patchwork.example.com"
[ingress]
listen = "127.0.0.1:2525"
[smtp]
host = "localhost"
port = 25
from = "patchwork@example.com"
Initialize the Database
Create the database schema and seed default data:
$ pw db sync
Create an Admin User
Create a user account with admin privileges:
$ pw admin user create --admin -u admin -e admin@example.com
The command will prompt for a password interactively.
Create a Project
Create your first project:
$ pw admin project create \
-n "My Project" \
-l my-project \
-i my-project.example.com \
-e patches@example.com
Running Services
Patchwork consists of two long-running services:
pw httpThe HTTP server exposing the web interface and REST API.
pw ingressThe SMTP daemon that receives emails from your mail transfer agent.
systemd
The make install target installs systemd unit files. Enable and start the
services:
$ sudo systemctl daemon-reload
$ sudo systemctl enable --now pw-http pw-ingress
The unit files are installed to /usr/lib/systemd/system/. To override
settings, use systemctl edit:
$ sudo systemctl edit pw-http
Note
Both services read configuration from /etc/patchwork.toml by default.
Use the PATCHWORK_TOML environment variable to specify an alternative
path.
Reverse Proxy
A reverse proxy like nginx is recommended for TLS termination and static file
serving. The make install target installs a default nginx configuration to
/etc/nginx/conf.d/patchwork.conf.
A minimal nginx configuration:
server {
listen 443 ssl;
server_name patchwork.example.com;
ssl_certificate /etc/letsencrypt/live/patchwork.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/patchwork.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
Incoming Email
Patchwork needs to receive emails from your mailing list. The recommended
approach is to configure your mail transfer agent to forward messages to the
pw ingress SMTP daemon.
Postfix with Transport Maps
This is the recommended setup. Configure Postfix to route mail for your list
domain to the pw ingress daemon using transport maps.
Add to /etc/postfix/main.cf:
transport_maps = lmdb:/etc/postfix/transport
Create /etc/postfix/transport:
lists.example.com smtp:127.0.0.1:2525
Build the transport map and reload Postfix:
$ sudo postmap /etc/postfix/transport
$ sudo systemctl reload postfix
All mail addressed to lists.example.com will now be forwarded to
pw ingress over SMTP. No shell scripts, no special user accounts, no
database grants.
Note
The pw ingress daemon matches incoming emails to projects by their
List-ID header. Make sure the -e (list email) and -i (list ID)
values of your project match what your mailing list software produces.
IMAP/POP3
For simpler setups, you can use a mail retriever like getmail to download messages from an inbox and pipe them to Patchwork:
[destination]
type = MDA_external
path = /usr/bin/pw
arguments = ("ingress", "--stdin",)
Manual Import
For one-off imports, pw ingress can read from stdin:
$ pw ingress --stdin < email.eml
$ pw ingress --mbox < archive.mbox
The --list-id flag can be used to override the List-ID header.
(Optional) VCS Integration
Patchwork can update patch states automatically when commits are pushed. A
post-receive Git hook can be configured to mark patches as “accepted” when
their corresponding commits land in the repository.
Refer to the post-receive.hook script in the Patchwork source tree for an
example implementation that uses the REST API.
Periodic Cleanup
Run garbage collection periodically to clean up expired sessions, stale email confirmations, and inactive users:
$ pw admin gc
A cron job or systemd timer is recommended (e.g. /etc/cron.daily/patchwork-gc):
#!/bin/sh
exec /usr/bin/pw admin gc