> ## Documentation Index
> Fetch the complete documentation index at: https://docs.alginte.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Production deployment

> The security boundary, reverse proxies, container configuration, and running multiple Alginte instances.

This page covers what changes when Alginte moves from a laptop to real infrastructure:
owning the network boundary, configuring the container properly, and how multiple
instances behave.

## The security boundary

Alginte ships with **no authentication by default** — *reachability is the access
control*. Two defaults implement that boundary:

* **`server.address=localhost`** — a plain `java -jar` serves only the local machine.
* A **trimmed actuator surface** — only `/actuator/health`, `/actuator/info`, and
  `/actuator/metrics` are exposed; heap dumps, env, loggers, and the rest are not.

Overriding the bind (`--server.address=0.0.0.0`, or the `SERVER_ADDRESS` env var) — or
publishing the container's port, which is the same moment in Docker form — is when
**you take ownership of the boundary**: anyone who can reach the port has full control
of every connected Kafka cluster unless the [login](/operate/authentication) is enabled.

For network exposure, put a **reverse proxy** in front (TLS termination, network
allow-listing) and enable a login. If you use OIDC behind the proxy, forward the
standard `X-Forwarded-*` headers and set `server.forward-headers-strategy=framework` —
details in [OIDC provider setup](/operate/oidc-setup#behind-a-reverse-proxy-https).

<Info>
  The Docker image bakes in `SERVER_ADDRESS=0.0.0.0` — a loopback-bound process inside
  a container would be unreachable through published ports. The container network and
  your proxy provide the boundary instead.
</Info>

## Configuring a container

Three ways, in increasing order of ceremony:

1. **Plain environment variables** (covers most cases) — Spring relaxed binding maps
   env vars onto any property (naming rules in [Configuration](/operate/configuration)):

   ```shell theme={null}
   docker run -p 8888:8888 \
     -e SPRING_KAFKA_BOOTSTRAPSERVERS=<kafka-host>:9092 \
     -e ALGINTE_AUTH_USERNAME=admin \
     -e ALGINTE_AUTH_PASSWORD='<a-strong-password>' \
     alginte/alginte:latest
   ```

2. **A Spring profile** — `-e SPRING_PROFILES_ACTIVE=<name>` activates a profile.
   Environment variables always win over profile values, so you can activate a profile
   for its bulk settings and still override individual hosts with env vars.

3. **Bring your own properties file** — mount it into `/app/config/` (Spring Boot's
   default config location relative to the image's workdir) and activate it:

   ```shell theme={null}
   docker run -p 8888:8888 \
     -v ./application-prod.properties:/app/config/application-prod.properties \
     -e SPRING_PROFILES_ACTIVE=prod \
     alginte/alginte:latest
   ```

   This is the recommended route for configuration too long for env vars — for
   example a full [OIDC provider block](/operate/oidc-setup).

`JAVA_OPTS` is the JVM tuning hook; the JDK's container-aware memory ergonomics are
the default, so most deployments need nothing there.

## What the image provides

* **Non-root**: runs as a dedicated system user (uid 1001).
* **Health check** built in: the container reports health via `/actuator/health`
  (60-second start period) — orchestrators and `docker ps` see it without extra config.
* **Layered image**: dependencies and application code live in separate layers, so
  pulling an upgraded tag downloads only the small application layer.
* **Fail-fast startup**: an unreachable broker stops the container with a clear
  message rather than a half-alive UI (see [Run with Docker](/installation/docker)
  for the networking pitfalls and the escape hatch).

## Multiple instances and recovery

Covered in [Running multiple instances](/installation/jar#running-multiple-instances):
instances are self-contained (run as many as you like), scaling a topology across
instances works the standard Kafka Streams consumer-group way, and **recovery is
restart, not replica** — processing state and progress live on the cluster itself.
Beyond deployed streams, Alginte is effectively **stateless app-side**: everything it
shows is cluster/upstream state it reads live.
