# Deploying Potato on Jetstream2

Source: https://www.potatoannotator.com/docs/deployment/deploy-jetstream2

`potato deploy up --provider openstack --cloud jetstream2` puts an annotation study on [Jetstream2](https://jetstream-cloud.org), an NSF-funded research cloud, where it costs nothing beyond your allocation's service units. Researchers at US institutions get Jetstream2 time through an [ACCESS](https://access-ci.org) allocation, so a study with no budget can still run on a dedicated machine with a disk that survives restarts. Each instance gets a DNS name under `projects.jetstream-cloud.org`, so annotators see an ordinary hostname with an ordinary HTTPS certificate. This page needs Potato 2.10 or later and a config you have already run with `potato start`.

## Getting a Jetstream2 allocation and credential

Jetstream2 runs on OpenStack cloud software, and Potato reaches it through OpenStack. Potato authenticates with an OpenStack *application credential*, a key tied to one allocation that you can revoke on its own. Setting one up takes three steps:

1. Request an ACCESS Explore allocation at [allocations.access-ci.org](https://allocations.access-ci.org) and ask for Jetstream2 CPU time.
2. Sign in to Jetstream2's Horizon dashboard at [js2.jetstream-cloud.org](https://js2.jetstream-cloud.org), create an application credential, and download its `clouds.yaml` file.
3. Save the file as `~/.config/openstack/clouds.yaml` and name its entry `jetstream2`, which is the name Potato's Jetstream2 defaults are keyed to.

Then install the OpenStack extra and check that the credential works:

```bash
pip install 'potato-annotation[deploy-openstack]'
potato deploy providers --verify
```

## Deciding who can sign in

`potato deploy` does not change your sign-in settings, and a Jetstream2 hostname is public. If the config lets anyone register, the dry run below reports warning D003, "Anyone who finds the URL can register and annotate." For a crowdsourced study, open registration is usually intended. For named annotators, list them under `user_config.users` with `allow_all_users: false` ([Password Management](/docs/deployment/password-management)) or have them sign in through your institution ([SSO and OAuth](/docs/deployment/sso-oauth)) before you deploy.

## Checking the plan

A dry run creates nothing and prints every step of the deploy, the hostname the task will have, and what the instance will cost your allocation:

```bash
potato deploy up myproject/config.yaml --provider openstack --cloud jetstream2 --dry-run
```

The plan creates one `m3.small` instance with 2 vCPUs from the `Featured-Ubuntu24` image, on your allocation's auto-allocated network, with a floating IP from the `public` network. A security group allows inbound ports 22, 80 and 443 only. Because the default login user differs between Jetstream2 images, Potato creates its own `potato-deploy` user holding a deploy key generated for this deployment. `--size` picks another flavor, `--network` names a network when the allocation has no auto-allocated one, and `--volume-gb` adds a separate volume for the task's data. An `m3.small` uses 2 service units (SUs, the allocation's currency) an hour, about 17,520 over a year if it is left running, so destroy the instance when the study ends.

## Deploying

Run the same command without `--dry-run`, and confirm the plan when Potato asks:

```bash
potato deploy up myproject/config.yaml --provider openstack --cloud jetstream2
```

The task is served at `https://potato-<name>.<allocation>.projects.jetstream-cloud.org`, where `<name>` comes from the task name. Jetstream2 publishes the DNS name a minute or two after the floating IP is attached, and Potato waits for it before requesting a 90-day Let's Encrypt certificate. The deploy ends by printing the URL and the path of the admin key file, `.potato/secrets.json` beside your config. The admin key opens the [admin dashboard](/docs/features/admin-dashboard) at `/admin`.

During the study, `potato deploy status` reports whether the server and its certificate are healthy, and `potato deploy logs myproject/config.yaml -f` follows the server log. Running `up` again after you edit the config uploads the new version to the same instance.

## Ending the study

The annotations are on the instance's disk, which is deleted with the instance. Pull them to your machine first, check them, and then remove the instance:

```bash
potato deploy pull myproject/config.yaml
potato deploy destroy myproject/config.yaml
```

`pull` writes everything the deployment collected into a new `potato-pull-<name>-<timestamp>` directory. `destroy` will not run on a deployment that has never been pulled. Once it has run, the instance stops using SUs.

## Campus OpenStack clouds

The same provider works on a campus OpenStack cloud. Put its `clouds.yaml` entry under any name and pass that name to `--cloud`. Without the Jetstream2 defaults, Potato uses the `m1.small` flavor, an `Ubuntu 24.04` image and the `public` external network, and `--size`, `--os-image` and `--network` override them. A campus cloud gives the instance no DNS name, so the task is served at its floating IP with a short-lived IP certificate, as on the [AWS Lightsail](/docs/deployment/deploy-aws) target.

## Troubleshooting

**"No --network given and this project has no auto-allocated network"** means the allocation has no default network. Create a network and router in Horizon or Exosphere and pass `--network <name>`.

**The certificate takes a few minutes** on the first deploy, because the DNS name has to resolve before Let's Encrypt can issue it.

## Further reading

- [Running Potato Locally or in the Cloud](/docs/deployment/quick-deploy), for the other cloud targets
- [Deploying an Annotation Server](/docs/guides/deploying-annotation-server), for choosing a host
- [Jetstream2 and OpenStack reference](https://github.com/davidjurgens/potato/blob/master/docs/deployment/deploy-openstack.md)
