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

# Upgrade to Astro Private Cloud 1.0 from 0.37

This guide provides instructions to upgrade from Astro Private Cloud (APC) 0.37.6 to 1.0.0 and prepare your environment for Airflow 3 Deployments.

<Warning>
  **Upgrade requires platform downtime**

  This upgrade deletes and recreates several platform components (NATS, STAN, Houston). The platform will be unavailable for creating or updating Deployments during the upgrade. Plan a maintenance window and notify your users before starting.
</Warning>

## Prerequisites

* [Upgrade to APC 0.37.6](/docs/astro-private-cloud/v-0-37/upgrade-astronomer) if you're on an earlier version.
* Back up your platform database. At minimum, create a snapshot or backup of your PostgreSQL database (RDS snapshot, Azure backup, Cloud SQL backup, or `pg_dump`).
* Verify that all platform and Airflow Deployment Pods are healthy:
  ```bash wrap theme={null}
  # Check platform pods
  kubectl get pods -n astronomer
  # Check Airflow deployment pods (replace with your deployment namespace)
  kubectl get pods -n astronomer-<deployment-release-name>
  ```
* If you use Astronomer Units (AU) for resource configuration, [convert to CPU/memory settings](/docs/astro-private-cloud/v-1-x/breaking-changes-removals#removal-of-astronomer-units-au-and-standardization-of-cpu/memory-settings) **before upgrading**. The AU-to-CPU/memory migration script was removed in 1.0, so you must complete this conversion while still on 0.37.x.
* Check for duplicate workspace labels in your database. The upgrade includes a migration that adds a unique constraint to workspace labels, and it will fail if duplicates exist:
  ```sql wrap theme={null}
  SET search_path TO "houston$default";
  SELECT label, COUNT(*) FROM "Workspace" GROUP BY label HAVING COUNT(*) > 1;
  ```
  If this query returns any results, rename or remove the duplicate workspaces before proceeding. See [Debug upgrade](/docs/astro-private-cloud/v-1-x/debug-upgrade#houston-migration-fails-due-to-duplicate-workspace-labels) for details.
* Remove any deprecated Helm values from your `values.yaml` that are no longer recognized in 1.0. See [Breaking changes and removals](/docs/astro-private-cloud/v-1-x/breaking-changes-removals) for the full list.
* (Optional) Capture logs from your NATS and STAN instances before the upgrade:
  ```bash wrap theme={null}
  kubectl logs -n astronomer -l component=nats --tail=1000 > nats-pre-upgrade.log
  kubectl logs -n astronomer -l component=stan --tail=1000 > stan-pre-upgrade.log
  ```

<Tip>
  For help with upgrade issues, see [Debug upgrade](/docs/astro-private-cloud/v-1-x/debug-upgrade).
</Tip>

<Warning>
  **Manual DNS and load balancer update required**

  When upgrading from Astro Private Cloud (APC) 0.`x.x` to 1.0.0, APC creates a new control plane NGINX ingress Service (`astronomer-cp-nginx`) and a new LoadBalancer. The previous ingress and LoadBalancer are replaced.

  You must:

  * Update all DNS records to the new load balancer IP address.
  * Update firewall, allowlist, and security rules to point to the new public endpoint.
  * Re-issue or update any TLS/SSL certificates that reference the previous LoadBalancer hostname, if applicable.

  This change occurs because the control plane ingress Service name changes from `astronomer-nginx` (0.x) to `astronomer-cp-nginx` (1.0), which causes Kubernetes to provision a new external LoadBalancer with a new public IP/hostname. Prepare these updates before performing the upgrade.

  Example (your output will vary by cloud/provider):

  ```sh wrap theme={null}
  kubectl -n astronomer get svc astronomer-cp-nginx
  NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP                                        PORT(S)                      AGE
  astronomer-cp-nginx  LoadBalancer   10.100.223.78   7666ac61ef6-1683718677.us-east-2.elb.amazonaws.com 80:32255/TCP,443:32647/TCP  25d
  ```

  <Note>
    If you are on OpenShift and manage your own Routes or use a third-party ingress controller instead of the platform's built-in NGINX ingress, this LoadBalancer change does not apply to you. You can skip the DNS update step later in this guide.
  </Note>
</Warning>

## Step 1: Validate the Helm upgrade (dry run)

Before making any changes to your cluster, run a Helm upgrade dry run to verify that the upgrade will succeed. This catches issues like missing RBAC permissions, invalid values, or chart conflicts before any components are deleted.

First, ensure that your `values.yaml` includes the unified mode configuration required for APC 1.0 (the same configuration referenced later in this guide); you do not need to duplicate that YAML block here.
Then run the dry run:

```bash wrap theme={null}
helm upgrade -f values.yaml -n astronomer astronomer astronomer/astronomer --version 1.0.x --dry-run
```

Replace `1.0.x` with the specific patch version you are upgrading to (for example, `1.0.1`).

<Warning>
  Do not proceed with the remaining steps until the dry run completes successfully. If the dry run fails, resolve the reported errors first.
</Warning>

## Step 2: Delete existing STAN and NATS StatefulSets

Before upgrading to version 1.0.0, you **must [migrate from STAN to JetStream](/docs/astro-private-cloud/v-1-x/breaking-changes-removals).**
Run the following commands in your cluster to remove legacy STAN components before JetStream is initialized:

```sh wrap theme={null}
kubectl delete sts <release-name>-stan
kubectl delete sts <release-name>-nats --cascade=orphan
```

## Step 3: Patch astronomer-bootstrap secret with database name

Before running the Helm upgrade, ensure the `astronomer-bootstrap` secret includes a database name suffix in `connection` (for example, `/postgres`). This prevents Postgres connection errors during or after the upgrade.

### Check your current connection string

First, check if your connection string already includes a database name:

```bash wrap theme={null}
kubectl get secret -n astronomer astronomer-bootstrap \
  --template='{{.data.connection | base64decode }}'
```

Examine the output. A connection string with a database name looks like:

```text wrap theme={null}
postgresql://user:pass@host:5432/postgres
                                 ^^^^^^^^
                                 database name present
```

A connection string **without** a database name looks like:

```text wrap theme={null}
postgresql://user:pass@host:5432
                                ^
                                no database name
```

If your connection string already includes a database name (for example, `/postgres` or `/astronomer`), you can skip to [Step 4](#step-4-delete-the-houston-deployment).

### Determine the correct database name

The default database name depends on your cloud provider:

* **AWS RDS**: `postgres` (standard default; `main` may appear only in specific legacy or custom configurations)
* **Azure Database for PostgreSQL**: `postgres`
* **GCP Cloud SQL**: `postgres`

If you're unsure which database to use, connect to your PostgreSQL instance using your preferred method (`psql`, a database client, or cloud console) and run `\l` to list available databases.

### Patch the secret

After confirming the database name, patch the `astronomer-bootstrap` secret:

```bash wrap theme={null}
# Namespace where APC is installed
NAMESPACE=astronomer
# Database name - verify using the steps above
DB_NAME=postgres

# Read current connection string, append database name, and update the secret
CURRENT=$(kubectl -n "$NAMESPACE" get secret astronomer-bootstrap -o jsonpath='{.data.connection}' | base64 -d)
NEW="${CURRENT%/}/$DB_NAME"
kubectl -n "$NAMESPACE" patch secret astronomer-bootstrap --type=merge -p "{\"data\":{\"connection\":\"$(printf '%s' "$NEW" | base64 -w0)\"}}"
```

## Step 4: Delete the Houston Deployment

Before running the Helm upgrade, delete the Houston Deployment to avoid a known Helm patch conflict related to environment variable ordering changes between versions.

```bash wrap theme={null}
kubectl delete deployment/<release-name>-houston -n astronomer --cascade=orphan
```

The `--cascade=orphan` flag keeps the Houston Pods running during the delete operation. The Helm upgrade in the next step recreates the Deployment with the correct configuration.

<Tip>
  If you skip this step and encounter a Helm patch error during the upgrade, see [Debug upgrade](/docs/astro-private-cloud/v-1-x/debug-upgrade#helm-upgrade-fails-with-patch-conflict) for the workaround.
</Tip>

## Step 5: Upgrade to APC 1.0

When upgrading from 0.37.x, you must configure your deployment to run in **unified** plane mode. Unified mode is equivalent to how 0.37.x operates and is required for the initial upgrade.

If you haven't already, add the following configuration to your `values.yaml`:

```yaml wrap theme={null}
global:
  plane:
    mode: "unified"
```

<Note>
  After upgrading to 1.0 in unified mode, you can optionally add separate Data Planes to run Airflow Deployments in other clusters. See [Install a Data Plane](/docs/astro-private-cloud/v-1-x/install-data-plane) for instructions. If you later want to convert your unified installation to a dedicated Control Plane (after migrating all Deployments to Data Planes), see [Install a Control Plane](/docs/astro-private-cloud/v-1-x/install-control-plane).
</Note>

Complete all pre-upgrade steps (database backup, STAN/NATS deletion, bootstrap secret patch, Houston Deployment deletion) before running the upgrade command.

Perform a standard Helm upgrade using your existing release name and namespace:

```bash wrap theme={null}
helm upgrade -f values.yaml -n astronomer astronomer astronomer/astronomer --version 1.0.x
```

Replace `1.0.x` with the specific patch version you are upgrading to (for example, `1.0.1`).

<Note>
  **Airgapped environments**

  For airgapped environments that cannot access the internet, download the Helm chart `.tgz` file directly from the Astronomer Helm repository:

  ```text wrap theme={null}
  https://helm.astronomer.io/astronomer-<version>.tgz
  ```

  Replace `<version>` with the specific version you are upgrading to (for example, `1.0.1`). Upload this file to your internal artifact repository (such as Artifactory or Nexus), then reference it in your `helm upgrade` command.
</Note>

## Step 6: Restart NATS and Houston components

After the platform upgrade completes and all Pods are running, restart NATS and Houston components to ensure the new JetStream components and Houston services are connected and synchronized:

```sh wrap theme={null}
kubectl rollout restart sts/<release-name>-nats
kubectl rollout restart deploy/<release-name>-houston
kubectl rollout restart deploy/<release-name>-houston-worker
```

After the rollout completes, verify the pods have been recreated by checking their age:

```bash wrap theme={null}
kubectl get pods -n astronomer -l "component in (nats,houston,houston-worker)" -o wide
```

All pods should show a recent `AGE` (a few minutes). If any pods show an older age, delete them manually to force recreation:

```bash wrap theme={null}
kubectl delete pod -n astronomer -l component=nats
kubectl delete pod -n astronomer -l component=houston
kubectl delete pod -n astronomer -l component=houston-worker
```

## Step 7: Update DNS records

APC 1.0 creates a new control plane NGINX ingress Service (`astronomer-cp-nginx`) with a new LoadBalancer. Get the new load balancer address:

```bash wrap theme={null}
kubectl -n astronomer get svc astronomer-cp-nginx
```

Update your DNS records to point to the new load balancer IP or hostname. This includes all subdomains for your base domain (for example, `app.<baseDomain>`, `houston.<baseDomain>`, `registry.<baseDomain>`).

<Note>
  If you are on OpenShift and manage your own Routes or use a third-party ingress controller, you can skip this step. Your existing ingress configuration continues to work.
</Note>

<Note>
  You must complete this step before you can access the Astro UI or API.
</Note>

## Step 8: Upgrade all Airflow Deployments

Once you have validated that all platform Pods in APC 1.0 are healthy and running, upgrade your Airflow Deployments to ensure compatibility with 1.0.

<Note>
  Existing Airflow Deployments typically continue to function after the platform upgrade without immediate action. However, Astronomer recommends upgrading Deployments to ensure full compatibility with the new platform version.
</Note>

To upgrade Deployments, use one of the following approaches:

* **Astro UI**: Upgrade each Deployment manually from the Astro UI by navigating to the Deployment and triggering an upgrade.
* **Houston API**: Use the [Houston API `upsertDeployment` mutation](/docs/astro-private-cloud/v-1-x/houston-upsert-deployment) for programmatic or bulk upgrades.
* **Astro CLI**: Use the Astro CLI's [astro deploy](/docs/cli/v1.43/astro-deploy) command.

## Step 9: Post-upgrade validation

After you complete your upgrade, validate your upgrade works as expected by completing the following steps:

<Steps>
  <Step title="Confirm that NATS pods are running with JetStream enabled.">
    Check if the JetStream job is created:

    ```bash wrap theme={null}
    kubectl -n astronomer get jobs | grep jetstream
    ```

    Check if NATS pods are running:

    ```bash wrap theme={null}
    kubectl -n astronomer get pods -l component=nats
    ```
  </Step>

  <Step title="Verify Houston Worker pods are healthy and processing events.">
    Check if Houston Worker pods are running:

    ```bash wrap theme={null}
    kubectl -n astronomer get pods -l component=houston-worker
    ```
  </Step>

  <Step title="Verify there are no remaining references to STAN.">
    This command should return no results:

    ```bash wrap theme={null}
    kubectl -n astronomer get statefulsets | grep stan
    ```
  </Step>

  <Step title="Verify you can access the Astro UI.">
    Navigate to `app.<baseDomain>` in your browser and confirm the UI loads.
  </Step>
</Steps>

## Next steps

* **Configuration model**: In APC 1.x, per-cluster `deployments.*` settings move out of `values.yaml` and into the platform database. Review [Configure Astro Private Cloud](/docs/astro-private-cloud/v-1-x/configure-astro-private-cloud) to learn which settings now live in cluster configuration and how to manage them from the Astro UI or the Houston API.
* **Airflow 3**: To create Airflow 3 Deployments, see [Migrate to Airflow 3](/docs/astro-private-cloud/v-1-x/migrate-to-airflow-3) for the required cluster configuration.
* **Data Planes**: To add separate Data Planes for running Airflow Deployments in other clusters, see [Install a Data Plane](/docs/astro-private-cloud/v-1-x/install-data-plane).
