Install WeCare Resolve Community Edition
This article explains how install WeCare Resolve Community Edition on a server with Docker Compose.
Quick start
Create an empty directory and save the two files from Installation files in it:
compose.yamland.env.Edit
.env:DOMAIN_NAME=localhost:8080andDOMAIN_PROTOCOL=httpAPP_MASTER_KEY,POSTGRES_PASSWORD,DATABASE_APP_PASSWORD: each the output ofopenssl rand -hex 32RESOLVE_BOOTSTRAP_ADMIN_EMAILandRESOLVE_BOOTSTRAP_ADMIN_PASSWORD: your sign-in as the first administratorRESOLVE_BOOTSTRAP_UNIT_NAME: your organisation’s name
Start it:
docker compose up -dOnce
curl -s http://localhost:8080/q/health/readyreports"status": "UP", open http://localhost:8080 and sign in with the email and password from.env.
Advanced installation
Requirements
A 64-bit Linux server (x86-64 or ARM64) with at least 1 GB of free memory.
Docker Engine 24 or newer with the Compose plugin. Check with:
docker compose versionAccess from the server to
containers.wecaredigital.eu, where Docker downloads the WeCare Resolve image from.A host name for WeCare Resolve, for example
resolve.example.com, whose DNS record points at the server or at your reverse proxy.A reverse proxy with a TLS certificate for that host name (see Set up a reverse proxy).
Outbound SMTP to your mail server.
opensslto generate the secrets (installed on most Linux systems).
Prepare the installation directory
Create a directory for the two files WeCare Resolve needs, for example /opt/resolve:
sudo mkdir -p /opt/resolve
cd /opt/resolve
Save the two files from Installation files in it:
compose.yaml: unchanged..env: you fill it in during the next steps.
.env will contain secrets, so only administrators should be able to read it:
chmod 600 .env
Generate the secrets
WeCare Resolve needs three secrets. Generate each one separately with:
openssl rand -hex 32
Put the results into .env:
| Setting | Purpose |
|---|---|
APP_MASTER_KEY | encrypts sensitive settings stored by WeCare Resolve, such as mail passwords and integration tokens |
POSTGRES_PASSWORD | the database administrator password |
DATABASE_APP_PASSWORD | the password of the restricted database account the application uses at runtime |
Back up
APP_MASTER_KEYnow, outside the server, for example in your password manager. A database backup cannot be decrypted without it. If the key is lost, every encrypted setting has to be entered again.
Never change APP_MASTER_KEY on a running installation. If you need to replace it, see Rotating the master key.
First start
Fill in the remaining values in .env:
| Setting | Example | Meaning |
|---|---|---|
RESOLVE_IMAGE | containers.wecaredigital.eu/wecare/resolve-ce:2 | the container image to run |
DOMAIN_NAME | resolve.example.com | the host name, without https:// |
RESOLVE_PORT | 8080 | the port on 127.0.0.1 that your reverse proxy forwards to |
RESOLVE_BOOTSTRAP_ADMIN_EMAIL | it@example.com | sign-in of the first administrator |
RESOLVE_BOOTSTRAP_ADMIN_PASSWORD | their initial password | |
RESOLVE_BOOTSTRAP_UNIT_NAME | City of Example | your organisation’s name, shown top left in the app |
RESOLVE_BOOTSTRAP_LANGUAGE | de | the default language (de, en, …) |
RESOLVE_BOOTSTRAP_MAP_CENTER | 52.52,13.405,5000 | optional: where the map starts, as latitude,longitude[,radius in metres] |
The RESOLVE_BOOTSTRAP_* values are only read while WeCare Resolve is being set up for the first time. They cannot change an existing installation.
Start WeCare Resolve:
docker compose up -d
The first start downloads the images and creates the database. Follow it with:
docker compose logs -f resolve
WeCare Resolve is ready when this prints "status": "UP":
curl -s http://127.0.0.1:8080/q/health/ready
If a required value is missing or invalid, WeCare Resolve stops with Installation incomplete in the log and names the value. Docker then restarts it every few seconds. Correct .env and run docker compose up -d again.
Sign in and remove the bootstrap values
Until your reverse proxy is set up, you can reach WeCare Resolve through an SSH tunnel from your workstation:
ssh -L 8080:127.0.0.1:8080 your-server
Open http://localhost:8080 and sign in with the administrator email and password from .env. Change the password under your account settings.
Then remove the bootstrap values, so the password no longer sits in the container’s configuration. Clear these lines in .env:
RESOLVE_BOOTSTRAP_ADMIN_EMAIL=
RESOLVE_BOOTSTRAP_ADMIN_PASSWORD=
RESOLVE_BOOTSTRAP_UNIT_NAME=
RESOLVE_BOOTSTRAP_MAP_CENTER=
and apply the change:
docker compose up -d
Set up a reverse proxy
A reverse proxy has to:
- serve
DOMAIN_NAMEover HTTPS with a valid certificate; - forward to
http://127.0.0.1:8080(or yourRESOLVE_PORT); - pass WebSocket connections on
/api/graphql, which carry live updates; - pass the original
Hostheader and setX-Forwarded-Proto; - accept request bodies of up to 250 MB, for attachments;
- allow long-lived connections (one hour or more) for the WebSocket.
WeCare Resolve ignores X-Tenant-Id, X-Tenant-Slug and X-Tenant-Proxy-Secret headers unless it is set up for several tenants, so a single-organisation installation needs no special handling for them.
nginx
# In the http block, once:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name resolve.example.com;
ssl_certificate /etc/ssl/resolve.example.com/fullchain.pem;
ssl_certificate_key /etc/ssl/resolve.example.com/privkey.pem;
client_max_body_size 250m;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 1h;
}
}
Caddy
Caddy obtains the certificate itself and handles WebSockets and the forwarding headers on its own:
resolve.example.com {
request_body {
max_size 250MB
}
reverse_proxy 127.0.0.1:8080
}
Check the proxy
Open https://resolve.example.com and sign in. Open an issue in two browser windows and change its status in one: the other window updates within a few seconds if WebSockets pass through the proxy.
Finish the setup in the app
Sign in as the administrator and open Settings:
- Email: WeCare Resolve sends no email until you enter your SMTP server here and turn email on. Invitations and notifications depend on it.
- User Management: invite your colleagues. There is no public sign-up.
- Map: OpenStreetMap is used by default. Here you can change the map provider and where the map starts.
- Domain: shows the host name from
DOMAIN_NAME. Leave it unchanged: a host name saved on this page takes precedence over.envfrom then on.
Updates
Before updating, read the release notes and back up all data (see Backup and restore).
The image tag :2 follows every 2.x release. To update to the latest one, run in the installation directory:
docker compose pull
docker compose up -d
A new major version gets a new tag, for example :3. To move to it, change RESOLVE_IMAGE in .env and run the same commands.
The application may be unavailable for a minute or two while it migrates the database. To see the progress, run docker compose logs -f resolve.
Backup and restore
A complete backup consists of:
.env, which containsAPP_MASTER_KEY;- a database dump;
- the
resolve-datavolume.
Back up
Run these commands in the installation directory:
docker compose exec -T db pg_dumpall -U postgres | gzip > resolve-db-$(date +%F).sql.gz
docker compose run --rm --no-deps --user root -v "$PWD:/backup" --entrypoint tar resolve \
czf /backup/resolve-data-$(date +%F).tar.gz -C /deployments data
Copy both files and .env to a safe place outside the server. Use pg_dumpall, not pg_dump: the dump must include the database accounts WeCare Resolve uses.
Restore
Restore into an installation directory with the same compose.yaml and the same .env:
docker compose down -v
docker compose up -d db
gunzip -c resolve-db-2026-10-07.sql.gz | docker compose exec -T db psql -U postgres -d postgres
docker compose run --rm --no-deps --user root -v "$PWD:/backup" --entrypoint tar resolve \
xzf /backup/resolve-data-2026-10-07.tar.gz -C /deployments
docker compose up -d
docker compose down -v deletes the current data. During the restore, role "postgres" already exists and database "resolve" already exists are expected.
Troubleshooting
To see the application log, run:
docker compose logs --tail 200 resolve
| Symptom | Cause and fix |
|---|---|
WeCare Resolve restarts every few seconds; the log says Installation incomplete | A bootstrap value is missing or invalid on the first start. The log names it. Fix .env, then docker compose up -d. |
docker compose up reports set APP_MASTER_KEY in .env (or another name) | That value is empty in .env. |
The log says Unable to connect to the database and WeCare Resolve never becomes ready | Check docker compose ps db and docker compose logs db. POSTGRES_PASSWORD must not change after the first start: the database keeps the password it was created with. |
502 Bad Gateway from the proxy | WeCare Resolve is not ready yet or RESOLVE_PORT differs from the proxy’s target. Check with curl -s http://127.0.0.1:8080/q/health/ready. |
Uploads fail with 413 Request Entity Too Large | Raise the proxy’s body limit to 250 MB (client_max_body_size in nginx). |
| Pages do not update until reloaded | The proxy does not pass WebSockets on /api/graphql. |
| Encrypted settings (mail password, integrations) stopped working after a restore | APP_MASTER_KEY differs from the one the backup was made with. |
Uninstalling
docker compose down -v
This removes the containers and all data. Without -v, the volumes and your data stay in place.
Reference: settings in .env
| Setting | Required | Default | Meaning |
|---|---|---|---|
RESOLVE_IMAGE | yes | container image to run | |
DOMAIN_NAME | yes | public host name | |
DOMAIN_PROTOCOL | no | https | http only if browsers reach WeCare Resolve without TLS; session cookies then lose the Secure flag |
RESOLVE_PORT | no | 8080 | loopback port for the reverse proxy |
APP_MASTER_KEY | yes | encryption key for sensitive settings | |
POSTGRES_PASSWORD | yes | database administrator password | |
DATABASE_APP_PASSWORD | yes | runtime database account password | |
RESOLVE_BOOTSTRAP_ADMIN_EMAIL | first start | first administrator | |
RESOLVE_BOOTSTRAP_ADMIN_PASSWORD | first start | first administrator’s password | |
RESOLVE_BOOTSTRAP_UNIT_NAME | first start | organisation name | |
RESOLVE_BOOTSTRAP_LANGUAGE | no | en | default language |
RESOLVE_BOOTSTRAP_MAP_CENTER | no | initial map view; the radius defaults to 10000 m |
Rotating the master key
Replacing the master key means re-encrypting the stored values, so back up first (see Backup and restore). WeCare Resolve then runs with a keyring instead of a single key. Add both settings to compose.yaml under environment:
APP_KEYS: a JSON object with every key, for example{"v1":"<current APP_MASTER_KEY>","v2":"<new key>"}. It takes precedence overAPP_MASTER_KEY.ACTIVE_KEY_VERSION: the key used for new values, for examplev2.
WeCare Resolve still reads values written with any key in the keyring. Keep every key in your backup.
Installation files
compose.yaml
# WeCare Resolve Community Edition. Settings come from .env next to this file.
services:
resolve:
image: ${RESOLVE_IMAGE:?set RESOLVE_IMAGE in .env}
restart: unless-stopped
depends_on:
db:
condition: service_healthy
# Plain HTTP on the loopback only: your HTTPS reverse proxy forwards to it.
ports:
- "127.0.0.1:${RESOLVE_PORT:-8080}:8080"
volumes:
- resolve-data:/deployments/data
environment:
APP_MASTER_KEY: ${APP_MASTER_KEY:?set APP_MASTER_KEY in .env}
DOMAIN_NAME: ${DOMAIN_NAME:?set DOMAIN_NAME in .env}
DOMAIN_PROTOCOL: ${DOMAIN_PROTOCOL:-https}
DATABASE_TYPE: PostgreSQL
DATABASE_HOST: db
DATABASE_NAME: resolve
DATABASE_USER: postgres
DATABASE_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
DATABASE_APP_PASSWORD: ${DATABASE_APP_PASSWORD:?set DATABASE_APP_PASSWORD in .env}
# Read on the first start only; clear them in .env afterwards.
RESOLVE_BOOTSTRAP_ADMIN_EMAIL: ${RESOLVE_BOOTSTRAP_ADMIN_EMAIL:-}
RESOLVE_BOOTSTRAP_ADMIN_PASSWORD: ${RESOLVE_BOOTSTRAP_ADMIN_PASSWORD:-}
RESOLVE_BOOTSTRAP_UNIT_NAME: ${RESOLVE_BOOTSTRAP_UNIT_NAME:-}
RESOLVE_BOOTSTRAP_LANGUAGE: ${RESOLVE_BOOTSTRAP_LANGUAGE:-en}
RESOLVE_BOOTSTRAP_MAP_CENTER: ${RESOLVE_BOOTSTRAP_MAP_CENTER:-}
db:
image: postgres:18-alpine
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql
environment:
POSTGRES_DB: resolve
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres", "-d", "resolve"]
interval: 5s
retries: 12
volumes:
resolve-data:
db-data:
.env
# Save as .env next to compose.yaml and fill in every value.
# The container image to run. The tag :2 follows every 2.x release.
RESOLVE_IMAGE=containers.wecaredigital.eu/wecare/resolve-ce:2
# Public host name, without https://. Your reverse proxy serves it over HTTPS.
DOMAIN_NAME=resolve.example.com
# https behind a reverse proxy; http only for a trial on localhost (DOMAIN_NAME=localhost:8080).
DOMAIN_PROTOCOL=https
# Port on 127.0.0.1 that your reverse proxy forwards to.
RESOLVE_PORT=8080
# Generate each secret with: openssl rand -hex 32
# APP_MASTER_KEY encrypts sensitive data. Back it up; without it that data is lost.
APP_MASTER_KEY=
POSTGRES_PASSWORD=
DATABASE_APP_PASSWORD=
# First start only: the first administrator and the name of your organisation.
RESOLVE_BOOTSTRAP_ADMIN_EMAIL=admin@example.com
RESOLVE_BOOTSTRAP_ADMIN_PASSWORD=
RESOLVE_BOOTSTRAP_UNIT_NAME=
RESOLVE_BOOTSTRAP_LANGUAGE=en
# Optional initial map view: latitude,longitude[,radius in metres], e.g. 52.52,13.405,5000
RESOLVE_BOOTSTRAP_MAP_CENTER=
Contact WeCare
We welcome bug reports and feature requests. Contact us through our website at wecaredigital.eu.