Skip to content

Commit 0bd22c2

Browse files
authored
VM IaC Updates (#187)
* Make VM IaC install more robust * VM IaC Doco
1 parent 2a5ffe9 commit 0bd22c2

File tree

21 files changed

+176
-42
lines changed

21 files changed

+176
-42
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,14 @@ To run the application in a container; download the [source](https://github.com/
8585
1. [Configure](https://oracle-samples.github.io/ai-optimizer/client/configuration/index.html) the **AI Optimizer**.
8686

8787
#### Got OCI?
88-
The **AI Optimizer** can be deployed with an Oracle Autonomous Database 23ai using infrastructure as code. Deploy the **AI Optimizer** in Oracle Cloud Infrastructure using OCI Resource Manager:
8988

89+
The **AI Optimizer** can be deployed in Oracle Cloud Infrastructure (OCI) using Infrastructure as Code (IaC).
90+
91+
Choose either a light-weight Virtual Machine or robust Oracle Kubernetes Engine deployment, both with an Oracle Autonomous Database 23ai:
9092
[![Deploy to Oracle Cloud][magic_button]][magic_arch_stack]
9193

94+
For more information, please visit the [IaC Documentation](https://oracle-samples.github.io/ai-optimizer/advanced/iac/index.html).
95+
9296
## Contributing
9397

9498
This project welcomes contributions from the community. Before submitting a pull request, please [review our contribution guide](./CONTRIBUTING.md).

docs/content/advanced/iac.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
+++
2+
title = 'Infrastructure as Code'
3+
weight = 1
4+
+++
5+
6+
<!--
7+
Copyright (c) 2024, 2025, Oracle and/or its affiliates.
8+
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
9+
10+
spell-checker: ignore opentofu Ollama
11+
-->
12+
13+
The {{< full_app_ref >}} can easily be deployed in Oracle Cloud Infrastructure (**OCI**) using Infrastructure as Code (**IaC**) provided in the source [opentofu](https://github.com/oracle-samples/ai-optimizer/tree/main/opentofu) directory.
14+
15+
Choose between deploying a light-weight [Virtual Machine](#virtual-machine) or robust [Oracle Kubernetes Engine (**OKE**)](#oracle-kubernetes-engine) along with the Oracle Autonomous Database for a fully configured {{< short_app_ref >}} environment, ready to use.
16+
17+
While the **IaC** can be run from a command-line with prior experience, the steps outlined here use [Oracle Cloud Resource Manager](https://docs.oracle.com/en-us/iaas/Content/ResourceManager/Concepts/resourcemanager.htm) to simplify the process. To get started:
18+
19+
{{< imagelink url="https://cloud.oracle.com/resourcemanager/stacks/create?zipUrl=https://github.com/oracle-samples/ai-optimizer/releases/latest/download/ai-optimizer-stack.zip" src="https://oci-resourcemanager-plugin.plugins.oci.oraclecloud.com/latest/deploy-to-oracle-cloud.svg" alt="Deploy to Oracle Cloud" >}}
20+
21+
## Virtual Machine
22+
23+
The Virtual Machine (VM) deployment provisions both the {{< short_app_ref >}} API Server and GUI Client together in an "All-in-One" configuration for experimentation and development. As part of the deployment, one local Large Language Model and one Embedding Model is made available out-of-the-box. However, as these models will be running on a CPU VM, their performance will be very poor.
24+
25+
### Configure Variables
26+
27+
After clicking the "Deploy to Oracle Cloud" button and authenticating to your tenancy; you will be presented with the {{< short_app_ref >}} stack information.
28+
29+
1. Review the Terms, tick the box to accept (if you do), and click "Next" to Configure Variables
30+
31+
![Stack Information](../images/iac_stack_information.png)
32+
33+
1. Change the Infrastructure to "VM"
34+
35+
![Stack - AI Optimizer](../images/iac_stack_optimizer.png)
36+
37+
#### Access Control
38+
39+
Most of the other configuration options are self-explanatory, but let's highlight those important for the **Security** of your deployment.
40+
41+
* The {{< short_app_ref >}} is often configured with authentication details for your OCI Tenancy, Autonomous Database, and API Keys for AI Models. Since these details are accessible via the Application GUI, access must be restricted to a limited set of CIDR blocks.
42+
43+
* The {{< short_app_ref >}} REST endpoints require API token authentication, providing some protection. However, you should still restrict access to a limited set of CIDR blocks where possible for added security.
44+
45+
* The Oracle Autonomous Database requires mTLS authentication with a wallet, providing strong initial protection. However, it's recommended to further restrict access to a limited set of CIDR blocks.
46+
47+
![Stack - Access Control](../images/iac_stack_access_control.png)
48+
49+
To restrict access, provide a comma-separated list of CIDR blocks, for example: `192.168.1.0/24,10.0.0.0/16,203.0.113.42/32`
50+
51+
In this example:
52+
* `192.168.1.0/24` – Allows access from all IPs in the range 192.168.1.0 to 192.168.1.255 (a typical subnet).
53+
* `10.0.0.0/16` – Allows access from 10.0.0.0 to 10.0.255.255 (a broader range).
54+
* `203.0.113.42/32` – Allows access from a single public IP address only. The /32 denotes a single host.
55+
56+
### Review and Apply
57+
58+
After configuring the variables, click "Next" to review and apply the stack.
59+
60+
![Stack - Review and Apply](../images/iac_stack_review_apply.png)
61+
62+
Tick the Apply box and click "Create".
63+
64+
### Job Details
65+
66+
The next screen will show the progress of the Apply job. Once the job has Succeeded, the {{< short_app_ref >}} has been deployed!
67+
68+
The Application Information tab will provide the URL's to access the {{< short_app_ref >}} GUI and API Server. In the "All-in-One" deployment on the VM, the API Server will only become accessible after visiting the GUI at least once.
69+
70+
![Stack - VM Application Information](../images/iac_stack_vm_info.png)
71+
72+
{{% notice style="code" title="502 Bad Gateway: Communication Breakdown!" icon="fire" %}}
73+
Although the infrastructure is deployed, the {{< short_app_ref >}} may still be initializing, which can result in a 502 Bad Gateway error when accessing the URLs. Please allow up to 10 minutes for the configuration to complete.
74+
{{% /notice %}}
75+
76+
To get a better understanding of how the API Server works and to obtain the API Key for making REST calls, review the [API Server documentation](client/api_server/).
77+
78+
### Cleanup
79+
80+
To destroy the {{< short_app_ref >}} infrastructure, in **OCI** navigate to `Developer Services` -> `Stacks`. Choose the Compartment the {{< short_app_ref >}} was deployed into and select the stack Name. Click on the "Destroy" button.
81+
82+
## Oracle Kubernetes Engine
83+
84+
{{% notice style="code" title="Documentation is Hard!" icon="circle-info" %}}
85+
More information coming soon... 11-June-2025
86+
{{% /notice %}}
Loading
Loading
Loading
Loading
27.4 KB
Loading
Loading

docs/content/client/api_server/_index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ Copyright (c) 2024, 2025, Oracle and/or its affiliates.
77
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
88
-->
99

10-
The {{< full_app_ref >}} is powered by an API Server to allow for any client to access its features. The API Server can be run as part of the provided {{< short_app_ref >}} GUI client or as a separate, independent process.
10+
The {{< full_app_ref >}} is powered by an API Server to allow for any client to access its features. The API Server can be run as part of the provided {{< short_app_ref >}} GUI client (referred to as the "All-in-One" deployment) or as a separate, independent process.
1111

1212
Each client connected to the API Server, including those from the {{< short_app_ref >}} GUI client, share the same configuration but maintain their own settings. Database, Model, OCI, and Prompt configurations are used across all clients; but which database, models, OCI profile, and prompts set are specific to each client.
1313

14-
When started as part of the {{< short_app_ref >}} client, you can change the Port it listens on and the API Server Key. A restart is required for the changes to take effect.
14+
When started as part of the {{< short_app_ref >}} "All-in-One" deployment, you can change the Port it listens on and the API Server Key. A restart is required for the changes to take effect.
1515

1616
![Server Configuration](images/api_server_config.png)
1717

docs/content/client/configuration/model_config.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ weight = 10
66
Copyright (c) 2024, 2025, Oracle and/or its affiliates.
77
Licensed under the Universal Permissive License v1.0 as shown at http://oss.oracle.com/licenses/upl.
88
9-
spell-checker:ignore ollama, mxbai, nomic, thenlper, minilm, uniqueid, huggingface, hftei, openai, pplx
9+
spell-checker:ignore ollama, mxbai, nomic, thenlper, minilm, uniqueid, huggingface, hftei, openai, pplx, genai, ocid, configfile
1010
-->
1111

1212
## Supported Models
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<a href="{{ .Get "url" }}">
2+
<img src="{{ .Get "src" }}" alt="{{ .Get "alt" }}">
3+
</a>

opentofu/main.tf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ module "vm" {
9292
adb_password = local.adb_password
9393
streamlit_client_port = local.streamlit_client_port
9494
fastapi_server_port = local.fastapi_server_port
95-
source_repository = var.source_repository
9695
compute_os_ver = var.compute_os_ver
9796
compute_cpu_ocpu = var.compute_cpu_ocpu
9897
compute_cpu_shape = var.compute_cpu_shape

opentofu/modules/network/main.tf

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ resource "oci_core_default_security_list" "lockdown" {
1919
compartment_id = oci_core_vcn.vcn.compartment_id
2020
display_name = format("%s-default-sec-list", var.label_prefix)
2121
manage_default_resource_id = oci_core_vcn.vcn.default_security_list_id
22+
egress_security_rules {
23+
description = "Egress for Bastion Access"
24+
destination = "0.0.0.0/0"
25+
destination_type = "CIDR_BLOCK"
26+
protocol = "all"
27+
stateless = "false"
28+
}
2229
}
2330

2431
// Public Subnet

opentofu/modules/network/variables.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ variable "infra" {
1717
variable "vcn_cidr" {
1818
type = map(any)
1919
default = {
20-
"VM" = ["10.42.0.0/28"]
20+
"VM" = ["10.42.0.0/27"]
2121
"Kubernetes" = ["10.42.0.0/16"]
2222
}
2323
}

opentofu/modules/vm/data.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,12 @@ data "oci_core_images" "images" {
2121

2222
data "oci_core_vcn" "vcn" {
2323
vcn_id = var.vcn_id
24+
}
25+
26+
data "oci_core_services" "core_services" {
27+
filter {
28+
name = "name"
29+
values = ["All .* Services In Oracle Services Network"]
30+
regex = true
31+
}
2432
}

opentofu/modules/vm/locals.tf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@ locals {
99
oci_region = var.region
1010
db_name = var.adb_name
1111
db_password = var.adb_password
12-
source_code = var.source_repository
1312
})
1413
}

opentofu/modules/vm/nsgs.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ resource "oci_core_network_security_group_security_rule" "vcn_icmp_ingress" {
2626
source_type = "CIDR_BLOCK"
2727
}
2828

29+
resource "oci_core_network_security_group_security_rule" "vcn_services_egress" {
30+
network_security_group_id = oci_core_network_security_group.compute.id
31+
description = "Compute OCI Services - All Ingress."
32+
direction = "INGRESS"
33+
protocol = "all"
34+
source = data.oci_core_services.core_services.services.0.cidr_block
35+
source_type = "SERVICE_CIDR_BLOCK"
36+
}
37+
2938
resource "oci_core_network_security_group_security_rule" "vcn_icmp_egress" {
3039
network_security_group_id = oci_core_network_security_group.compute.id
3140
description = "Compute Path Discovery - ICMP Egress."

opentofu/modules/vm/templates/cloudinit-compute.tpl

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,44 @@
22
# Copyright (c) 2024, 2025, Oracle and/or its affiliates.
33
# All rights reserved. The Universal Permissive License (UPL), Version 1.0 as shown at http://oss.oracle.com/licenses/upl
44
# spell-checker: disable
5-
6-
package_update: false
7-
packages:
8-
- git
9-
- python3.11
10-
115
users:
6+
- default
127
- name: oracleai
138
uid: 10001
14-
gid: 10001
159
shell: /bin/bash
1610
homedir: /app
1711

12+
package_update: false
13+
packages:
14+
- python36-oci-cli
15+
- python3.11
16+
1817
write_files:
18+
- path: /etc/systemd/system/ai-optimizer.service
19+
permissions: '0644'
20+
content: |
21+
[Unit]
22+
Description=Run app start script
23+
After=network.target
24+
25+
[Service]
26+
Type=simple
27+
ExecStart=/bin/bash /app/start.sh
28+
User=oracleai
29+
Group=oracleai
30+
WorkingDirectory=/app
31+
Environment="HOME=/app"
32+
Restart=on-failure
33+
34+
[Install]
35+
WantedBy=multi-user.target
36+
1937
- path: /tmp/root_setup.sh
2038
permissions: '0755'
2139
content: |
2240
#!/bin/env bash
41+
mkdir -p /app
42+
chown oracleai:oracleai /app
2343
curl -fsSL https://ollama.com/install.sh | sh
2444
systemctl enable ollama
2545
systemctl daemon-reload
@@ -28,31 +48,28 @@ write_files:
2848
firewall-offline-cmd --zone=public --add-port 8501/tcp
2949
firewall-offline-cmd --zone=public --add-port 8000/tcp
3050
systemctl start firewalld.service
31-
append: false
32-
defer: false
51+
3352
- path: /tmp/app_setup.sh
3453
permissions: '0755'
3554
content: |
3655
#!/bin/bash
3756
# Setup for Instance Principles
3857
export OCI_CLI_AUTH=instance_principal
3958

40-
# Setup oci config.ini to indicate to app to use instance_principal
41-
# mkdir -p /app/.oci
42-
# echo -e '[DEFAULT]\nregion=${oci_region}\ntenancy=${tenancy_id}' > /app/.oci/config
43-
# oci setup repair-file-permissions --file /app/.oci/config
44-
4559
# Download/Setup Source Code
46-
curl -L -o /tmp/source.tar.gz ${source_code}.tar.gz
60+
curl -s https://api.github.com/repos/oracle-samples/ai-optimizer/releases/latest \
61+
| grep tarball_url \
62+
| cut -d '"' -f 4 \
63+
| xargs curl -L -o /tmp/source.tar.gz
4764
tar zxf /tmp/source.tar.gz --strip-components=2 -C /app '*/src'
4865
cd /app
4966
python3.11 -m venv .venv
5067
source .venv/bin/activate
51-
pip3.11 install --upgrade pip wheel setuptools oci-cli
68+
pip3.11 install --upgrade pip wheel setuptools
5269
pip3.11 install torch==2.6.0+cpu -f https://download.pytorch.org/whl/cpu/torch
5370
pip3.11 install -e ".[all]" --quiet --no-input &
5471
INSTALL_PID=$!
55-
72+
5673
# Wait for Database and Download Wallet
5774
while [ $SECONDS -lt $((SECONDS + 600)) ]; do
5875
echo "Waiting for Database... ${db_name}"
@@ -64,7 +81,7 @@ write_files:
6481
break
6582
fi
6683
sleep 15
67-
done
84+
done
6885
mkdir -p /app/tns_admin
6986
unzip -o /tmp/wallet.zip -d /app/tns_admin
7087

@@ -75,18 +92,30 @@ write_files:
7592
# Wait for python modules to finish
7693
wait $INSTALL_PID
7794

78-
# Startup application
95+
- path: /app/start.sh
96+
permissions: '0750'
97+
content: |
98+
#!/bin/bash
99+
export OCI_CLI_AUTH=instance_principal
79100
export DB_USERNAME='ADMIN'
80101
export DB_PASSWORD='${db_password}'
81102
export DB_DSN='${db_name}_TP'
82103
export DB_WALLET_PASSWORD='${db_password}'
83104
export ON_PREM_OLLAMA_URL=http://127.0.0.1:11434
84-
export LOG_LEVEL=DEBUG
85-
nohup streamlit run launch_client.py --server.port 8501 --server.address 0.0.0.0 &
86-
append: false
87-
defer: false
105+
# Clean Cache
106+
find /app -type d -name "__pycache__" -exec rm -rf {} \;
107+
find /app -type d -name ".numba_cache" -exec rm -rf {} \;
108+
find /app -name "*.nbc" -delete
109+
# Set venv and start
110+
source /app/.venv/bin/activate
111+
streamlit run /app/launch_client.py --server.port 8501 --server.address 0.0.0.0
88112

89113
runcmd:
90114
- /tmp/root_setup.sh
91115
- su - oracleai -c '/tmp/app_setup.sh'
92-
- rm /tmp/app_setup.sh /tmp/root_setup.sh /tmp/source.tar.gz /tmp/wallet.zip
116+
- rm /tmp/app_setup.sh /tmp/root_setup.sh /tmp/source.tar.gz /tmp/wallet.zip
117+
- chown oracleai:oracleai /app/start.sh
118+
- systemctl daemon-reexec
119+
- systemctl daemon-reload
120+
- systemctl enable ai-optimizer.service
121+
- systemctl start ai-optimizer.service

opentofu/modules/vm/variables.tf

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,6 @@ variable "adb_password" {
5252
type = string
5353
}
5454

55-
variable "source_repository" {
56-
type = string
57-
}
58-
5955
variable "streamlit_client_port" {
6056
type = number
6157
}

opentofu/schema.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ variableGroups:
2929
variables:
3030
- adb_version
3131
- k8s_version
32-
- source_repository
3332
- compute_gpu_shape
3433
- compute_os_ver
3534
visible: false
@@ -236,7 +235,7 @@ variables:
236235

237236
adb_whitelist_cidrs:
238237
type: array
239-
title: "ADB Access Control"
238+
title: "Access Control for the Autonomous Database"
240239
required: true
241240
default: "0.0.0.0/0"
242241
pattern: "((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]).(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\\/(3[0-2]|[1-2]?[0-9])(,?)( ?)){1,}$"

opentofu/variables.tf

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,6 @@ variable "private_key_path" {
4949
default = ""
5050
}
5151

52-
variable "source_repository" {
53-
description = "Code that will pulled onto compute; ensure correct branch/tag."
54-
default = "https://github.com/oracle-samples/ai-optimizer/archive/refs/heads/main"
55-
}
56-
5752
// Infrastructure Type/Label
5853
variable "infrastructure" {
5954
description = "Choose between a full Kubernetes or a light-weight Virtual Machine deployment."

0 commit comments

Comments
 (0)