Skip to main content

Install for evaluation

This tutorial installs Foundation4 on a single Kubernetes node for evaluation, with PostgreSQL, NATS JetStream, Valkey and Prometheus installed from the bundled charts. At the end of the tutorial, the API answers on localhost and the master key is confirmed. Operators and integrators who want a working deployment to explore Foundation4 start here. Production installations follow Install on Kubernetes.

Evaluation profile​

The evaluation profile trades durability for a short installation path:

  • Bundled database. PostgreSQL runs in the cluster from the bundled chart and stores data on a temporary pod volume. Deleting or rescheduling the PostgreSQL pod deletes every pipeline and document. The new database also has a new system ID, so the license no longer matches and a new license is required.
  • Single node. Every component runs on one node. The charts set no resource requests or limits.
  • License. Foundation4 requires a license for every installation, including evaluation. The license is bound to the system ID of the database, which exists only after the installation creates the database schema. The installation therefore runs the application release twice: once to obtain the system ID and once with the license.

Requirements​

RequirementDetails
KubernetesOne node, such as a single-node k3s cluster. Model and package images, which need image volume support, are not used in this tutorial.
StorageA default StorageClass. The bundled charts request 38 GiB in volume claims: 3 claims of 10 GiB for NATS JetStream and 8 GiB for Prometheus.
Toolskubectl, Helm 3, openssl, uuidgen and curl. kubectl kustomize builds the secret.
Installation filesThe files supplied by the Foundation4 provider: the charts/foundation4ai-core and charts/foundation4ai charts, kustomization.yaml and foundation4ai.secrets.env.template.
ImagesThe registry path and release tag of the API server, gRPC service and dashboard images, and pull credentials if the registry requires them. PostgreSQL, NATS, Valkey and Prometheus images come from public registries.

Run every command in this tutorial from the directory that holds the installation files.

Evaluation values​

Both releases read one values file. Create evaluation.values.yaml with the following content, replacing each value in angle brackets:

global:
serverImageTag: "<api server image tag>"
grpcImageTag: "<grpc service image tag>"
dashboardImageTag: "<dashboard image tag>"

postgres:
enabled: true

api-server:
image:
repository: <registry>/foundation4ai-api
repositoryGrpc: <registry>/foundation4ai-grpc
replicaCount:
worker: 1

dashboard:
image:
repository: <registry>/foundation4ai-dashboard

The values file sets the following:

  • Image tags. The three tags are required. The charts provide no default tag.
  • Bundled PostgreSQL. postgres.enabled: true installs PostgreSQL with the pgvector extension. The default, false, expects an external database.
  • Workers. One worker replica instead of the default 3, to fit a small node.
  • Pull credentials. When the registry requires credentials, create an image pull secret in the foundation4ai namespace after step 1 and add the secret under global.imagePullSecrets as a list of name entries. This list applies to the Foundation4 pods of the application release; the core release pulls public images. Charts, images and installation bundle covers private mirrors of the core images.

Do not copy settings from the sample values file supplied with the charts. The sample file points model and package images at the provider's registry and enables debug logging.

Installation​

1. Namespace​

The kustomization file places the secret in the namespace foundation4ai, so every release in this tutorial uses that namespace.

kubectl create namespace foundation4ai

Expected result: namespace/foundation4ai created.

2. Secrets​

Copy the template:

cp foundation4ai.secrets.env.template foundation4ai.secrets.env

Generate the values. openssl rand -hex 24 produces a password or secret, uuidgen produces the master key identifier and the openssl rand -base64 32 command produces the application secret:

openssl rand -hex 24
uuidgen
openssl rand -base64 32 | tr '+/' '-_'

Edit foundation4ai.secrets.env and set the following keys. Leave POSTGRES_URL and REDIS_URL empty; the bundled charts build both connection URLs.

KeyValue
POSTGRES_DATABASEfoundation4ai
POSTGRES_USERfoundation4ai
POSTGRES_SUPERUSER_PASSWORDA new openssl rand -hex 24 value
POSTGRES_PASSWORDA new openssl rand -hex 24 value
REDIS_PASSWORDA new openssl rand -hex 24 value
FOUNDATION4AI_APP_SECRETThe openssl rand -base64 32 value: the application secret, which encrypts the stored API keys of LLMs
FOUNDATION4AI_APP_MASTER_KEYThe uuidgen value: the identifier of the master key
FOUNDATION4AI_APP_MASTER_SECRETA new openssl rand -hex 24 value: the secret of the master key
FOUNDATION4AI_APP_LICENSEpending until step 5

The following rules apply to these values:

  • Hexadecimal passwords. The charts insert the passwords into connection URLs without encoding, so characters such as @, / and % break the connection. The openssl rand -hex values contain only hexadecimal characters.
  • Master key. Record the master key identifier and secret. The master secret cannot be changed after installation, and the API server does not start if the master secret changes.
  • Application secret. Record the application secret. The stored API keys of LLMs cannot be decrypted without the application secret, and a new application secret requires the API key of each LLM to be set again.

Create the Kubernetes secret from the file:

kubectl kustomize . | kubectl apply -f -

Expected result: secret/foundation4ai-secrets created.

3. Core release​

The core release installs PostgreSQL, NATS JetStream, Valkey and Prometheus.

helm upgrade --install foundation4ai-core ./charts/foundation4ai-core \
-n foundation4ai -f evaluation.values.yaml --wait --timeout 10m
kubectl get pods,pvc -n foundation4ai

Expected result: Helm reports STATUS: deployed. The PostgreSQL, Valkey, Prometheus server and NATS utility pods and 3 NATS pods are Running, and 4 volume claims are Bound.

4. System ID​

The first application install runs the database migration, reports the system ID and then stops at the license check, because the license is still pending. The license check waits indefinitely after the report, so Helm stops the install at the timeout. This failure is expected.

helm upgrade --install foundation4ai ./charts/foundation4ai \
-n foundation4ai -f evaluation.values.yaml --timeout 3m
kubectl logs -n foundation4ai job/foundation4ai-api-server-license-check

Expected result: after 3 minutes, Helm reports that the pre-install hook failed. The log of the license check Job contains the system ID:

SystemID: <system ID>
Checking for a valid license... Invalid

5. License​

Send the system ID to the Foundation4 provider and receive the license. Replace pending with the license in foundation4ai.secrets.env, then update the secret, upgrade the core release so that the core release copies the license, and delete the waiting license check Job:

kubectl kustomize . | kubectl apply -f -
helm upgrade foundation4ai-core ./charts/foundation4ai-core \
-n foundation4ai -f evaluation.values.yaml --wait --timeout 10m
kubectl delete job -n foundation4ai foundation4ai-api-server-license-check

Expected result: secret/foundation4ai-secrets configured, Helm reports STATUS: deployed for foundation4ai-core, and job.batch "foundation4ai-api-server-license-check" deleted.

6. Application release​

Remove the failed release and install the application release again:

helm uninstall foundation4ai -n foundation4ai
helm install foundation4ai ./charts/foundation4ai \
-n foundation4ai -f evaluation.values.yaml --wait --timeout 10m
kubectl get jobs,pods -n foundation4ai
kubectl logs -n foundation4ai job/foundation4ai-api-server-license-check

Expected result: Helm reports STATUS: deployed. The database migration, license check and master key Jobs are complete. The API server pod shows 2/2 containers ready, the worker pod 2/2 and the dashboard pod 1/1. The license check log ends with the following line:

Checking for a valid license... OK

The API server pod and the worker pod each run two containers: the Foundation4 process and the gRPC service, which hosts the Python text splitters and embedding providers.

7. API access​

Forward a local port to the API server service in a separate terminal:

kubectl port-forward -n foundation4ai svc/foundation4ai-api-server 8080:80

Set the shell variables that the tutorials use, with the master key identifier and secret from step 2, and call the API:

export FOUNDATION4_URL=http://localhost:8080
export FOUNDATION4_API_KEY=<master key identifier>
export FOUNDATION4_API_SECRET=<master key secret>
curl -X POST "$FOUNDATION4_URL/login" \
-H "x-api-key: $FOUNDATION4_API_KEY" \
-H "x-api-key-secret: $FOUNDATION4_API_SECRET"

Expected result: status 201 and a body whose message is OK and whose key is Master Admin Key, followed by the permissions of the master key. The installation is complete. Authenticate creates a key for the remaining tutorials.

Dashboard access​

The dashboard is optional. The dashboard calls the API on the same host name, so the dashboard is reached through an ingress rather than a port forward. The chart's ingress sends /dashboard to the dashboard and every other path to the API server. k3s includes the Traefik ingress controller; on other clusters, className names the installed controller.

Add the following to evaluation.values.yaml:

ingress:
enabled: true
className: traefik
hosts:
- host: foundation4.localhost

Apply the change:

helm upgrade foundation4ai ./charts/foundation4ai \
-n foundation4ai -f evaluation.values.yaml --wait --timeout 10m

Expected result: http://foundation4.localhost/dashboard/ shows the dashboard sign-in page. The dashboard signs in with the master key identifier and secret.

Troubleshooting​

Pods or volume claims in pending status​

  • Symptoms. After step 3, NATS or Prometheus pods remain Pending, and kubectl get pvc -n foundation4ai shows claims in Pending status.
  • Diagnosis. kubectl get storageclass lists no class marked (default), or kubectl describe pvc -n foundation4ai reports that no storage class is set.
  • Cause. The bundled charts request volumes without naming a storage class, so the cluster needs a default StorageClass.
  • Resolution. Mark an existing StorageClass as the default, or install a local volume provisioner, then run step 3 again.
  • Actions to avoid. Deleting the NATS volume claims after documents have been added, which deletes queued documents.

Image pull errors​

  • Symptoms. Hook Job pods or application pods report ErrImagePull, ImagePullBackOff or InvalidImageName, and the install stops at the timeout.
  • Diagnosis. kubectl describe pod -n foundation4ai <pod name> shows the image reference and the registry response.
  • Cause. An image repository or tag in evaluation.values.yaml is missing or wrong, or the registry requires credentials that the values file does not reference.
  • Resolution. Correct the repository and tag values, create the image pull secret and list the secret under global.imagePullSecrets, then repeat the failed step.
  • Actions to avoid. Omitting the tags in the expectation of a default. The charts provide none.

Database migration failure​

  • Symptoms. The log of job/foundation4ai-api-server-db-migration shows Failed connecting to database.
  • Diagnosis. kubectl get pods -n foundation4ai shows whether a PostgreSQL pod exists and is Running. helm get values foundation4ai-core -n foundation4ai shows whether postgres.enabled is true.
  • Cause. postgres.enabled is not set, so the connection URL is empty, or a password contains characters that break the connection URL.
  • Resolution. Set postgres.enabled: true, or replace the passwords with hexadecimal values and reapply the secret. Then upgrade the core release and repeat step 4.
  • Actions to avoid. Deleting the PostgreSQL pod to force a new connection. The bundled database stores data on a temporary volume, so a new pod starts with an empty database and a new system ID.

API server or worker containers restarting​

  • Symptoms. After step 6, the server or worker container restarts repeatedly.
  • Diagnosis. kubectl logs -n foundation4ai deploy/foundation4ai-api-server -c server --previous shows the error. Failed to initialize Foundation4aiCore with master key points to the master key. Failed to create database connection with a license error points to the license.
  • Cause. The master key Job did not complete, the master secret changed after the first installation, or the license does not match the database.
  • Resolution. Confirm that job/foundation4ai-api-server-create-admin-api-key completed, restore the original master secret, or request a license for the current system ID.
  • Actions to avoid. Generating a new master secret for an existing installation.

Removal​

Remove the evaluation installation and every stored object:

helm uninstall foundation4ai -n foundation4ai
helm uninstall foundation4ai-core -n foundation4ai
kubectl delete namespace foundation4ai

Expected result: both releases are uninstalled and namespace "foundation4ai" deleted. The namespace deletion also removes the volume claims, the secrets and the completed Jobs.