Liking cljdoc? Tell your friends :D

Deployment Patterns

This guide covers deployment patterns beyond Docker. For the Docker path, see deployment.adoc and dev-docs/DOCKER_DEVELOPMENT.adoc. Reference configs live in resources/deploy/.

Prerequisites

Build the uberjar before any deployment:

clojure -T:build clean && clojure -T:build uber
# Produces target/wagoe-*.jar

Run migrations before starting the server:

java -jar target/wagoe-*.jar migrate up

Environment Variables

All deployments need these variables. See resources/deploy/systemd/wagoe.env.example for a full template.

VariableRequiredDescription

WAG_ENV

Yes

production (or acc for staging)

JWT_SECRET

Yes

32+ character signing secret

POSTGRES_HOST

Yes

Database hostname

POSTGRES_PORT

Yes

Database port (default 5432)

POSTGRES_DB

Yes

Database name

POSTGRES_USER

Yes

Database user

POSTGRES_PASSWORD

Yes

Database password

HTTP_PORT

No

App listen port (default 3000)

SENTRY_DSN

No

Error reporting DSN

REDIS_HOST

No

Required if cache/jobs enabled

REDIS_PASSWORD

No

Redis auth password

systemd (bare metal / VM)

Reference files: resources/deploy/systemd/

Setup

# 1. Create service user
sudo useradd -r -s /usr/sbin/nologin wagoe

# 2. Deploy the jar
sudo mkdir -p /opt/wagoe/{logs,data}
sudo cp target/wagoe-*.jar /opt/wagoe/wagoe.jar
sudo chown -R wagoe:wagoe /opt/wagoe

# 3. Configure secrets
sudo mkdir -p /etc/wagoe
sudo cp resources/deploy/systemd/wagoe.env.example /etc/wagoe/wagoe.env
sudo chmod 600 /etc/wagoe/wagoe.env
# Edit /etc/wagoe/wagoe.env with real values

# 4. Install and start the service
sudo cp resources/deploy/systemd/wagoe.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now wagoe

Operations

sudo systemctl status wagoe     # Check status
sudo journalctl -u wagoe -f     # Tail logs
sudo systemctl restart wagoe    # Restart after deploy

The unit file runs migrations via ExecStartPre before starting the server. On failure it restarts after 10 seconds, with a maximum of 5 retries per minute.

JVM Tuning

The unit file sets default JVM options. Adjust for your server:

# In wagoe.service — set heap to ~70% of available RAM
Environment=JAVA_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
Server RAMRecommended -Xmx

1 GB

512m

2 GB

1g

4 GB

2g-3g

8 GB+

4g-6g

nginx Reverse Proxy

Reference file: resources/deploy/nginx/wagoe.conf

# 1. Install
sudo cp resources/deploy/nginx/wagoe.conf /etc/nginx/sites-available/wagoe
sudo ln -s /etc/nginx/sites-available/wagoe /etc/nginx/sites-enabled/

# 2. Replace your-domain.com with your actual domain

# 3. TLS (Let's Encrypt)
sudo certbot --nginx -d your-domain.com

# 4. Test and reload
sudo nginx -t && sudo systemctl reload nginx

The config includes:

  • HTTP → HTTPS redirect

  • WebSocket upgrade support for /ws (realtime library)

  • Suppressed access logs on /health

  • 30-day cache for static assets

  • Connection keepalive to the app

Cloud Platforms

Fly.io

Reference file: resources/deploy/cloud/fly.toml

# 1. Install flyctl: https://fly.io/docs/getting-started/installing-flyctl/

# 2. Launch (first time)
fly launch --copy-config

# 3. Create database
fly postgres create --name my-wagoe-app-db
fly postgres attach my-wagoe-app-db

# 4. Set secrets
fly secrets set JWT_SECRET="your-secret-32-chars-min" POSTGRES_PASSWORD="..."

# 5. Deploy
fly deploy

The fly.toml configures:

  • Auto-scaling (min 1 machine, auto-stop idle)

  • Health checks against /health/ready

  • HTTPS enforcement

  • Amsterdam region (adjust primary_region as needed)

Render

Reference file: resources/deploy/cloud/render.yaml

  1. Push to GitHub

  2. Connect the repo on https://dashboard.render.com

  3. Select the render.yaml Blueprint

  4. Render auto-provisions PostgreSQL and wires environment variables

The blueprint configures:

  • Web service + managed PostgreSQL

  • Auto-generated JWT_SECRET

  • Health checks against /health/ready

  • Frankfurt region

Health Check Integration

All deployment patterns should use the health endpoints:

EndpointPurposeUse for

/health

Basic liveness + service info

Monitoring dashboards

/health/ready

Dependency checks (DB, cache)

Load balancer readiness probes, deploy gates

/health/live

Process alive

Container orchestrator liveness probes

/health/ready returns 503 when any dependency is unreachable, making it safe for load balancer health checks - traffic is not routed until the database is connected.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close