Skip to main content

Troubleshooting

This document was generated using AI assistance

Content may include inaccuracies, outdated information, or technical errors. Users are advised to cross-check critical information before implementation.

Start with the state of the stack. Every service has a health check, and a service that never turns healthy is the one to look at first:

docker compose ps
docker compose logs -f backend

backend and api-gateway answer on /actuator/health, frontend on /health, and keycloak on port 9000 at /health.

Sign-in redirects to localhost

The address the browser is sent to comes from the environment, not from the request. APPLICATION_URL, API_GATEWAY_URL, OAUTH2_ISSUER_URL, OAUTH2_AUTHORIZATION_URL and OAUTH2_ACCOUNT_URL must all be the public addresses of your installation. If any of them still says localhost, users outside the host end up at a page they cannot reach.

Keycloak reports an invalid redirect URI

The architeezy client accepts exactly one redirect URI, fixed when the realm was first imported: API_GATEWAY_URL/login/oauth2/code/keycloak. Changing API_GATEWAY_URL later does not change the client. Open Clients → architeezy in the Keycloak admin console and correct Valid redirect URIs and Valid post logout redirect URIs by hand.

The API gateway cannot reach Keycloak

OAUTH2_TOKEN_URL, OAUTH2_JWK_SET_URL and OAUTH2_USER_INFO_URL are called by the application itself, not by the browser, and must resolve from inside the container network - http://keycloak:8080/... in the bundled setup. A public HTTPS address works too, as long as the container can reach it.

If OAUTH2_JWK_SET_URL is wrong, the backend cannot verify tokens and every API call comes back as 401 even though sign-in appeared to succeed.

CORS errors in the browser console

The API gateway allows APPLICATION_URL, ABOUT_URL and APPLICATIONS_URL as origins. Add any other origin to ALLOWED_ORIGINS, or match it with ALLOWED_ORIGIN_PATTERNS, and restart the API gateway. That covers a second host name for the same instance, an embedded page, and an application of your own calling the API.

The backend cannot connect to the database

SPRING_DATASOURCE_USERNAME and SPRING_DATASOURCE_PASSWORD come from DATABASE_USERNAME and DATABASE_PASSWORD, which is also what the db container is initialised with. PostgreSQL only reads those on the first start against an empty volume: change DATABASE_PASSWORD afterwards and the database keeps the old one while the backend presents the new one.

Either change the password inside the database with ALTER USER, or start over with an empty volume - which deletes the data, so take a dump first.

User sessions end unexpectedly

Sessions are kept in Redis and disappear if redis was recreated without its volume, or if REDIS_PASSWORD no longer matches what the API gateway sends.

If sessions instead expire sooner than expected, compare SESSION_TIMEOUT with SSO Session Idle in the Keycloak realm. Both are 30 days as delivered, and the shorter of the two wins.

The application, the API gateway and Keycloak all build their URLs from the forwarded headers. A reverse proxy in front of them must set Host, X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Port. The configuration on the prebuilt images page sets all four.

Diagrams stop updating until the page is reloaded

Live updates run over a WebSocket on /subscriptions. A proxy that does not pass Connection: upgrade and Upgrade: $http_upgrade closes it. The sample configuration sets both, together with a long proxy_read_timeout, which the connection needs to stay open.

Uploading a large file fails

Three limits apply in sequence:

  • the reverse proxy in front of the stack;
  • the frontend container, which accepts up to 100 MB;
  • the backend, which accepts up to 256 MB per file.

The sample proxy configuration allows 50 MB - raise client_max_body_size there if you need more.

A port is already in use

Every published port is set by a variable in the .env file - FRONTEND_PORT, KEYCLOAK_PORT, DATABASE_PORT, REDIS_PORT and KEYCLOAK_DATABASE_PORT. Change the value and run docker compose up -d again. All of them are bound to 127.0.0.1, so a conflict is always with something else on the same host.

The AI assistant does not answer

The backend talks to an OpenAI-compatible service at OPENAI_URL, which points at host.docker.internal:11434 by default - a model server running on the host machine. If nothing listens there, the assistant fails while the rest of the application keeps working. Point OPENAI_URL, OPENAI_API_KEY and OPENAI_MODEL at the service you use.