Skip to content

Self-Hosting

Hosting your own PushGo Gateway gives you full control over your data and notifications. The gateway is a high-performance Rust binary.

The official Docker image is the easiest and most manageable way to deploy.

Terminal window
docker run -d --name pushgo-gateway \
-p 6666:6666 \
-p 5223:5223/tcp \
-p 5223:5223/udp \
-e PUSHGO_HTTP_ADDR=0.0.0.0:6666 \
-e PUSHGO_DB_URL='postgres://user:pass@db:5432/pushgo' \
-e PUSHGO_TOKEN='your_secure_token' \
-e PUSHGO_PRIVATE_CHANNEL_ENABLED=true \
-e PUSHGO_PRIVATE_TLS_CERT=/certs/fullchain.pem \
-e PUSHGO_PRIVATE_TLS_KEY=/certs/privkey.pem \
-v /etc/pushgo/certs:/certs:ro \
ghcr.io/aldenclark/pushgo-gateway:latest

You can run the prebuilt binary directly on a Linux server.

1. Download Binary

Terminal window
curl -fL -o pushgo-gateway \
https://github.com/AldenClark/pushgo-gateway/releases/latest/download/pushgo-gateway-amd64-musl
chmod +x pushgo-gateway

2. Build from Source (Optional)

If you need a custom build or are running on a non-Linux platform:

Terminal window
cargo build --release -p pushgo-gateway
./target/release/pushgo-gateway --db-url <DB_URL>

3. Systemd Service Management

On Linux, it is recommended to use systemd to manage the gateway process:

[Unit]
Description=PushGo Gateway
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=pushgo
Group=pushgo
WorkingDirectory=/opt/pushgo-gateway
ExecStart=/opt/pushgo-gateway/pushgo-gateway \
--http-addr 0.0.0.0:6666 \
--private-channel-enabled \
--db-url ${PUSHGO_DB_URL}
Environment=PUSHGO_DB_URL=postgres://user:pass@127.0.0.1:5432/pushgo
Environment=PUSHGO_PRIVATE_TLS_CERT=/etc/pushgo/certs/fullchain.pem
Environment=PUSHGO_PRIVATE_TLS_KEY=/etc/pushgo/certs/privkey.pem
Environment=PUSHGO_TOKEN=your_secure_token
Restart=always
RestartSec=2
LimitNOFILE=1048576
[Install]
WantedBy=multi-user.target

PushGo uses environment variables for configuration.

VariableDefaultDescription
PUSHGO_HTTP_ADDR127.0.0.1:6666HTTP API and WSS bind address
PUSHGO_DB_URL(Required)Database URL (Supports sqlite, postgres, mysql)
PUSHGO_TOKEN(Empty)Public API auth token (Bearer Token)
PUSHGO_PRIVATE_CHANNEL_ENABLEDfalseEnable Private Channels (Real-time transport)
PUSHGO_PUBLIC_BASE_URL(Empty)External base URL (Required for OAuth/WSS hints)
PUSHGO_TOKEN_SERVICE_URLhttps://token.pushgo.devToken service endpoint
VariableDefaultDescription
PUSHGO_PRIVATE_TLS_CERT(Empty)Path to TLS certificate (PEM)
PUSHGO_PRIVATE_TLS_KEY(Empty)Path to TLS private key (PEM)
PUSHGO_PRIVATE_QUIC_BIND127.0.0.1:5223QUIC listener bind address (UDP)
PUSHGO_PRIVATE_TCP_BIND127.0.0.1:5223Raw TCP listener bind address (TCP)
PUSHGO_PRIVATE_TCP_TLS_OFFLOADfalseWhether Raw TCP TLS is offloaded by proxy

server {
listen 443 ssl http2;
server_name gateway.example.com;
ssl_certificate /etc/nginx/certs/fullchain.pem;
ssl_certificate_key /etc/nginx/certs/privkey.pem;
location / {
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://127.0.0.1:6666;
}
}

If the gateway terminates TLS (Recommended):

stream {
server {
listen 5223;
proxy_pass 127.0.0.1:5223;
proxy_timeout 600s;
}
}
stream {
server {
listen 5223 udp;
proxy_pass 127.0.0.1:5223;
proxy_timeout 600s;
}
}

QUIC and Raw TCP (in non-offload mode) require the gateway to hold the TLS certificates directly. You can use Let’s Encrypt certificates. The certificates must cover the domain name used by clients.

PushGo’s QUIC layer uses a custom ALPN (pushgo-quic), which is NOT compatible with HTTP/3. If your Nginx already serves HTTP/3 on 443/udp, you MUST use a different UDP port for private QUIC (e.g., 5223/udp).

  • SQLite: sqlite:///data/pushgo.db?mode=rwc
  • PostgreSQL: postgres://user:pass@host:port/db
  • MySQL: mysql://user:pass@host:port/db

  1. Combined Transport: Enable both QUIC and Raw TCP, keeping WSS as a fallback for restricted networks.
  2. Edge Security: Bind the HTTP port to 127.0.0.1 and expose it only via Nginx/LB.
  3. Observability: Set PUSHGO_OBSERVABILITY_PROFILE=ops to enable operational metrics collection.