# Origin Cloud > Virtual machines, block storage and private networks in European data centers, with prices you can read before you register. Virtual machines, block storage and private networks in European data centers, with prices you can read before you register. These documents describe the template. Public documentation contains no account or organization data. Authenticated tools apply the same organization permissions as the app. ## Public pages - [Origin Cloud docs](https://origin.its-live.dev/docs): The seven Origin Cloud guides, from Platform to Pricing. - [Overview](https://origin.its-live.dev/index.md): Services, published rates and how to register, from the home page. - [Privacy policy](https://origin.its-live.dev/privacy.md): The template's privacy text and replacement notice. - [Terms of service](https://origin.its-live.dev/terms.md): The template's terms and replacement notice. - [Full documentation](https://origin.its-live.dev/llms-full.txt): Public pages, demo content and the agent connection guide. ## Origin Cloud docs The documentation is available in English only. UI language does not translate these documents. - [Create an image](https://origin.its-live.dev/docs/compute/images/create.md): Turn an instance's root disk into your own image - clear its machine-id, snapshot and protect the volume, create the image - and update or delete it later. - [Image families](https://origin.its-live.dev/docs/compute/images/image-families.md): How an image family resolves to its current platform-provided image, what its metadata tells you about upstream support, and what happens when one is withdrawn. - [Images](https://origin.its-live.dev/docs/compute/images.md): An image is what an instance boots from. Learn the difference between platform-provided and your own images, and what each image field means. - [What is Origin Cloud Compute?](https://origin.its-live.dev/docs/compute.md): Compute runs virtual machines on Origin Cloud. Learn how instances, images, instance types and key pairs fit together and how to reach them. - [Attach and detach volumes](https://origin.its-live.dev/docs/compute/instance-storage/attach-detach.md): Attach an available volume to a running or stopped instance, choose its guest device name, and detach it again to use elsewhere. - [Instance storage](https://origin.its-live.dev/docs/compute/instance-storage.md): How an instance's durable root disk is created and sized at launch, and how extra volumes attach to a running or stopped instance. - [Change an instance's type](https://origin.its-live.dev/docs/compute/instances/change-type.md): Change a stopped instance to a different instance type so it starts again with more or fewer vCPUs and memory, keeping its identity and volumes. - [Guest environment](https://origin.its-live.dev/docs/compute/instances/guest-environment.md): What the platform sets up inside an instance at first boot - the login user and SSH key, time synchronization - and why each image needs its own machine-id. - [Instance health checks](https://origin.its-live.dev/docs/compute/instances/health-checks.md): What each instance health check observes, how results combine into availability, and how the category tells you whether a problem is yours to fix. - [When the machine under an instance fails](https://origin.its-live.dev/docs/compute/instances/host-failure.md): What happens to an instance when its physical machine fails or is taken out of service, what survives, and why restarting it is your decision. - [Instances](https://origin.its-live.dev/docs/compute/instances.md): An instance is a virtual machine on Origin Cloud. Find its lifecycle, types, health checks, failure behavior and the tasks to launch and manage one. - [Instance types](https://origin.its-live.dev/docs/compute/instances/instance-types.md): How instance types set an instance's vCPU and memory, how type names are built, and how to read the live catalog and its available flag. - [Launch an instance](https://origin.its-live.dev/docs/compute/instances/launch.md): Launch a virtual machine with the CLI or the API - choose an image, instance type, key pair, network and root disk - and log in over SSH. - [Instance lifecycle](https://origin.its-live.dev/docs/compute/instances/lifecycle.md): The eight statuses an instance moves through from launch to termination, what changes each one, what you're billed for, and what FAILED means. - [Stop and start an instance](https://origin.its-live.dev/docs/compute/instances/stop-start.md): Stop an instance to release its vCPU and memory while keeping its disks and addresses, and start it again later, possibly on another machine. - [Terminate an instance](https://origin.its-live.dev/docs/compute/instances/terminate.md): Terminate an instance permanently, and learn which of its volumes, network interfaces and addresses are deleted and which stay with you. - [Create a key pair](https://origin.its-live.dev/docs/compute/key-pairs/create.md): Import the public half of an SSH key you already have, or have the platform generate a key pair and save its private key from the one response that carries it. - [Key pairs](https://origin.its-live.dev/docs/compute/key-pairs.md): A key pair is the SSH key you log in to instances with. Learn how the platform uses it at launch and what happens when you delete one. - [origin compute commands](https://origin.its-live.dev/docs/compute/reference/cli.md): Every origin compute command with its flags: instances, instance types, images, image families, key pairs and volume attachments. - [Compute reference](https://origin.its-live.dev/docs/compute/reference.md): Complete reference material for Compute - every origin compute command and its options, and every reason an instance can report in statusReason. - [Status reasons](https://origin.its-live.dev/docs/compute/reference/status-reasons.md): Every text an instance can report in statusReason when it is FAILED or was stopped by the platform, with what each means and what to do next. - [Troubleshoot Compute](https://origin.its-live.dev/docs/compute/troubleshooting.md): Fix common Compute problems - failed instances, refused launches and starts, impaired or unknown health, unsynchronized clocks, SSH failures and broken pod networking. - [Access model](https://origin.its-live.dev/docs/iam/access-model.md): How principals, roles, role assignments and permissions work together, how org-wide and project scopes differ, and how a request is authorized. - [Assign and revoke roles](https://origin.its-live.dev/docs/iam/assign-roles.md): Grant a built-in role to a user or service account org-wide or for one project, and revoke it again at exactly the scope it was granted. - [Audit log](https://origin.its-live.dev/docs/iam/audit-log.md): Which access changes the audit log records, the fields of each entry, who can read it, and how to page through it with the GraphQL API. - [Check access](https://origin.its-live.dev/docs/iam/check-access.md): Look up who you are and which roles you hold, list the platform's permissions, and check whether a principal has a permission on a resource. - [What is Origin Cloud IAM?](https://origin.its-live.dev/docs/iam.md): IAM controls who can do what in your Origin Cloud organization. Learn how principals, roles, role assignments and permissions fit together. - [Manage organization members](https://origin.its-live.dev/docs/iam/manage-members.md): Invite people to your organization by email, list members and pending invites, remove a member's access, and cancel an invite before it applies. - [origin iam commands](https://origin.its-live.dev/docs/iam/reference/cli.md): Every origin iam command with its flags: members, invites, service accounts, role assignments and permission checks. - [IAM reference](https://origin.its-live.dev/docs/iam/reference.md): Where to find every origin iam command and built-in role, and a one-line summary of each IAM query and mutation in the GraphQL API. - [Built-in roles](https://origin.its-live.dev/docs/iam/roles.md): Every built-in IAM role with its ID, URN, what it's for and the exact permissions it grants, including the billing roles that Owner doesn't include. - [Use service accounts](https://origin.its-live.dev/docs/iam/service-accounts.md): Create a service account for CI and scripts, exchange its client ID and secret for an access token, grant it roles, and revoke it. - [Origin Cloud Docs](https://origin.its-live.dev/docs.md): User documentation for Origin Cloud, for anyone calling the GraphQL API or the origin CLI. - [DNS](https://origin.its-live.dev/docs/network/dns.md): Every instance gets an internal hostname that its VPC resolves, and DNS policies decide where other queries go. Learn how names are resolved in a VPC. - [Manage DNS policies](https://origin.its-live.dev/docs/network/dns/manage-policies.md): Create DNS policies, change their upstream servers and relaying, attach a policy to a VPC, change a project's default policy, and delete a policy. - [What is Origin Cloud Network?](https://origin.its-live.dev/docs/network.md): Network gives your instances private VPCs, subnets and network interfaces, controlled internet access, traffic filtering and DNS. Learn how the parts fit. - [Floating IPs](https://origin.its-live.dev/docs/network/internet-access/floating-ips.md): A Floating IP is a public IPv4 address you hold and associate with a network interface. Learn how to use it, when it's released, and how it behaves inside its VPC. - [Internet access](https://origin.its-live.dev/docs/network/internet-access.md): How traffic gets between your instances and the internet - Internet Gateways, route tables, NAT gateways and Floating IPs, and the two paths they form. - [Attach and detach an Internet Gateway](https://origin.its-live.dev/docs/network/internet-access/internet-gateways.md): Attach an Internet Gateway to connect a whole VPC to the internet, check it, and detach it again to make the VPC private. - [Give a private subnet internet access with a NAT gateway](https://origin.its-live.dev/docs/network/internet-access/nat-gateways.md): Create a NAT gateway so instances without a Floating IP can reach the internet over IPv4, route a private subnet through it, and delete it again. - [Route tables](https://origin.its-live.dev/docs/network/internet-access/route-tables.md): How route tables decide where a subnet's internet traffic goes, how the main table differs from tables you create, and how to change routes and associations. - [origin network commands](https://origin.its-live.dev/docs/network/reference/cli.md): Every origin network command with its flags: VPCs, subnets, gateways, route tables, Floating IPs, ACLs, security groups and DNS policies. - [Network reference](https://origin.its-live.dev/docs/network/reference.md): Where to find every origin network CLI command and every GraphQL query and mutation in the network namespace of the API. - [Traffic control](https://origin.its-live.dev/docs/network/traffic-control.md): Security groups filter each instance's traffic and network ACLs filter traffic crossing a subnet's boundary. Learn where each one applies. - [Network ACLs](https://origin.its-live.dev/docs/network/traffic-control/network-acls.md): Network ACLs are stateless, ordered rule lists for a subnet. Learn how rules are evaluated, which traffic they apply to, and how to create and assign one. - [Rule sets are replaced as a whole](https://origin.its-live.dev/docs/network/traffic-control/replace-rule-sets.md): ACL rules, security group rules and DNS upstream servers are replaced as a whole. Learn how each command makes you state the full new state, including an empty one. - [Security groups](https://origin.its-live.dev/docs/network/traffic-control/security-groups.md): Security groups are stateful firewalls on each network interface. Learn how rules and group references work, what the default group allows, and how to change rules. - [Troubleshoot Network](https://origin.its-live.dev/docs/network/troubleshooting.md): Fixes for common Network problems - no internet access, IPv6 errors, refused VPC, subnet and NAT gateway requests, and connections that hang. - [VPC and subnet addressing](https://origin.its-live.dev/docs/network/vpcs/addressing.md): How a VPC's IPv4 and IPv6 ranges are chosen, how large its subnets are, which addresses are reserved, and what happens when address space runs out. - [Create a VPC and subnets](https://origin.its-live.dev/docs/network/vpcs/create.md): Create a VPC with the CLI, add subnets to it, and choose whether instances launched into each subnet get a public IPv4 address automatically. - [Default VPC](https://origin.its-live.dev/docs/network/vpcs/default-vpc.md): The platform creates a default VPC for a project the first time you launch an instance without a subnet. Learn what it contains and how auto-assigned public IPs work. - [Delete a subnet or VPC](https://origin.its-live.dev/docs/network/vpcs/delete.md): Delete a subnet or a whole VPC, clear what blocks the deletion, and learn what is removed with it and what happens to its address ranges. - [VPCs and subnets](https://origin.its-live.dev/docs/network/vpcs.md): A VPC is an isolated network with its own address space, divided into subnets. Learn what a VPC comes with and how instances connect to it. - [Network interfaces](https://origin.its-live.dev/docs/network/vpcs/network-interfaces.md): A network interface holds an instance's private IPv4 and IPv6 addresses in a subnet and carries its security groups. Learn how interfaces are created and removed. - [What is Origin Cloud Observability?](https://origin.its-live.dev/docs/observability.md): Observability lets you query CPU, network, and disk metrics that the platform collects for your instances, volumes, and network interfaces. - [Query metrics](https://origin.its-live.dev/docs/observability/query-metrics.md): Query the CPU, network, or volume metrics of one resource over a time window with the GraphQL API, and choose the period and statistic. - [Observability reference](https://origin.its-live.dev/docs/observability/reference.md): Reference pages for Observability, listing every metric with its unit and meaning, the metrics query arguments, limits, and errors. - [Metrics reference](https://origin.its-live.dev/docs/observability/reference/metrics.md): Every metric Observability provides, with resource type, unit, and meaning, plus the metrics query arguments, response fields, limits, and errors. - [Use the GraphQL API](https://origin.its-live.dev/docs/platform/access/api.md): Call the Origin Cloud GraphQL API with a bearer token, find operations by namespace, read resource URNs, and handle typed enums and errors. - [Use the CLI](https://origin.its-live.dev/docs/platform/access/cli.md): Install the origin CLI, log in through your browser or with a device code, manage your session and profile, and read the CLI's JSON output and exit codes. - [Ways to access Origin Cloud](https://origin.its-live.dev/docs/platform/access.md): Reach Origin Cloud through the console, the origin CLI or the GraphQL API. All three act as a signed-in user or service account with the same permissions. - [Billing access](https://origin.its-live.dev/docs/platform/billing/billing-access.md): Billing is kept apart from the Owner role. Learn which billing roles reach a billing account, who holds one from the start, and what an Owner can do without one. - [Billing](https://origin.its-live.dev/docs/platform/billing.md): Billing accounts hold your billing details and payment method, and every project is charged to one. Learn how billing accounts, payment methods, invoices and spend limits fit together. - [Add a payment method](https://origin.its-live.dev/docs/platform/billing/payment-method.md): Add a card to a billing account on the payment provider's hosted page, confirm it, and check paymentMethodStatus so the account's projects can create billable resources. - [Get started with Origin Cloud](https://origin.its-live.dev/docs/platform/getting-started.md): Register an organization, add a payment method, launch your first instance with the origin CLI, log in to it over SSH, and clean up afterwards. - [What is Origin Cloud?](https://origin.its-live.dev/docs/platform.md): Origin Cloud runs virtual machines, block storage and private networks in European data centers. Learn how organizations, projects and resources fit together. - [Create an organization](https://origin.its-live.dev/docs/platform/organizations/create.md): Register an organization with its billing details in one step, or create it from its name alone and add the billing details to its default billing account later. - [Organizations and projects](https://origin.its-live.dev/docs/platform/organizations.md): An organization is your company's Origin Cloud account and holds your projects, members and billing accounts. Learn how they relate and what you can manage. - [Manage projects](https://origin.its-live.dev/docs/platform/organizations/projects.md): Create, list, rename and delete the projects in your organization, find a project's URN, change the billing account a project is charged to, and delete an organization. - [Organization review status](https://origin.its-live.dev/docs/platform/organizations/review-status.md): A new organization is activated at once or reviewed first, depending on platform capacity. Learn what each status allows, which emails you get, and how to check it. - [Platform CLI commands](https://origin.its-live.dev/docs/platform/reference/cli.md): Every origin id, origin admin and origin config command with its flags: log in, manage organizations and projects, and set CLI profile values. - [Error codes](https://origin.its-live.dev/docs/platform/reference/errors.md): Every error code the Origin Cloud API returns, with what it means, what commonly causes it, and what to do. Branch on the code, never on the message. - [Platform reference](https://origin.its-live.dev/docs/platform/reference.md): Look up the platform CLI commands, every error code the API returns with what to do about it, and the quotas and hard limits that apply to your organization. - [Limits](https://origin.its-live.dev/docs/platform/reference/limits.md): The quotas on what your organization and its projects can hold, how to read current usage against them, how to set project budgets, and the platform's hard limits. - [What is Origin Cloud Pricing?](https://origin.its-live.dev/docs/pricing.md): The public price list gives the current list price of every billable product, in euro, over HTTP without an account or token. - [Read the price list](https://origin.its-live.dev/docs/pricing/read-price-list.md): Fetch the public price list with curl, revalidate it with a conditional request, and turn a price into an hourly or monthly cost. - [Pricing reference](https://origin.its-live.dev/docs/pricing/reference.md): Reference pages for Pricing, covering the public price list endpoint, its response fields, product families, headers, and status codes. - [Price list API](https://origin.its-live.dev/docs/pricing/reference/price-list-api.md): Reference for GET /v1/pricing, the public price list endpoint, with every response field, product family, header, and status code. - [What is Origin Cloud Storage?](https://origin.its-live.dev/docs/storage.md): Storage gives your instances durable block volumes and point-in-time snapshots. Learn the parts, how they relate to images, and how to access them. - [origin storage commands](https://origin.its-live.dev/docs/storage/reference/cli.md): Every origin storage command with its flags: volumes, storage classes, imports and snapshots. - [Storage reference](https://origin.its-live.dev/docs/storage/reference.md): Look up every origin storage CLI command and every GraphQL query and mutation in the pvs namespace for volumes, snapshots, and storage classes. - [Create and protect a snapshot](https://origin.its-live.dev/docs/storage/snapshots/create-and-protect.md): Take a crash-consistent snapshot of an available or attached volume, wait for it to complete, and protect it so it can be used as a clone source. - [Delete a snapshot](https://origin.its-live.dev/docs/storage/snapshots/delete.md): Unprotect a snapshot if needed, delete it, and confirm that it reports DELETED so it no longer blocks deleting its volume. - [Snapshots](https://origin.its-live.dev/docs/storage/snapshots.md): A snapshot is a point-in-time copy of a volume. Learn how snapshots connect volumes to new volumes and images, and find the snapshot tasks. - [Snapshot states](https://origin.its-live.dev/docs/storage/snapshots/snapshot-states.md): The status and protection status values a snapshot reports, what FAILED protection means, and when a snapshot can be used as a clone source. - [Troubleshoot storage](https://origin.its-live.dev/docs/storage/troubleshooting.md): Fix common volume and snapshot problems, from volumes in ERROR and failed resizes to refused deletes, failed imports, and refused requests. - [Create a volume](https://origin.its-live.dev/docs/storage/volumes/create.md): Create an empty volume or a volume from a protected snapshot with the origin CLI or the GraphQL API, and check that it becomes AVAILABLE. - [Delete a volume](https://origin.its-live.dev/docs/storage/volumes/delete.md): Delete a volume you no longer need, after detaching it and deleting its snapshots, and confirm that it reports DELETED and frees its quota. - [Find the instance a volume is attached to](https://origin.its-live.dev/docs/storage/volumes/find-instance.md): Follow an INUSE volume's claimRef to its volume attachment and from there to the instance that holds it, with one CLI command or API query. - [Import a disk image as a volume](https://origin.its-live.dev/docs/storage/volumes/import.md): Create a volume whose initial content is a disk image downloaded from an HTTP(S) URL, size it correctly, and check that the import succeeded. - [Volumes](https://origin.its-live.dev/docs/storage/volumes.md): A volume is a durable block disk for your instances. Learn the key concepts and find the tasks for creating, resizing, and deleting volumes. - [Resize a volume](https://origin.its-live.dev/docs/storage/volumes/resize.md): Grow a volume, including one attached to a running instance, then extend the partition and filesystem inside the guest to use the new space. - [Storage classes](https://origin.its-live.dev/docs/storage/volumes/storage-classes.md): A storage class is a volume's performance tier. Learn which classes exist, which one you can select today, and how to read the catalog. - [Volume states](https://origin.its-live.dev/docs/storage/volumes/volume-states.md): The status and modification status values a volume reports, how asynchronous operations and failures show up in them, and which states are billed. ## Agent connection - [MCP endpoint](https://origin.its-live.dev/api/mcp): OAuth 2.1 authenticated MCP; start with tools/list to discover available tools. - [OAuth protected resource](https://origin.its-live.dev/.well-known/oauth-protected-resource): Resource metadata for MCP authorization. - [OAuth authorization server](https://origin.its-live.dev/.well-known/oauth-authorization-server): Authorization and token endpoints. - [API reference](https://origin.its-live.dev/api/rpc/api-reference): Session-authenticated oRPC API documentation. - [OpenAPI specification](https://origin.its-live.dev/api/rpc/api-reference/spec.json): Session-authenticated API schema. - [Sitemap](https://origin.its-live.dev/sitemap.xml): Public URLs only. Markdown pages support ?lang=en, ?lang=de and ?lang=fr. This index and the full document are in English. # European cloud infrastructure. Independent by design. Virtual machines, block storage and private networks in European data centers, with prices you can read before you register. No card to register · New organizations are activated at once or reviewed first, depending on capacity [Register](/signup) · [Pricing](/pricing) · [Docs](/docs) ## Five services. Provision them today. Compute, Persistent Volume Storage, VPC, IAM and Observability are live. Cost Management is coming soon. - [Compute](/services/compute): Virtual machines in the gp1 series, priced per hour at published rates. - [Persistent Volume Storage](/services/storage): Durable block volumes on general-purpose SSD, with point-in-time snapshots. - [VPC](/services/network): Isolated virtual networks: subnets, security groups, floating IPs and internet gateways. - [IAM](/services/iam): Organization members, invitations, built-in roles, service accounts and an audit log. - [Observability](/services/observability): Platform metrics for instances, volumes and network interfaces, queryable from the API. - [Cost Management](/services/cost-management) (Coming soon): Usage and cost reports, spend limits and billing accounts. In the API today; the service is coming soon. ## No quotes. No sales calls. Plain APIs. ### Real pricing, no quotes Every instance type and rate is in a public price list. No sales call is needed to find out what something costs. ### Refusals you can act on When a request is refused, you get an error code such as INSUFFICIENT_CAPACITY and a correlation ID to quote when you ask for help. ### Open by design A GraphQL API and a CLI with 117 commands cover every resource type, so Origin Cloud fits the tools you already use. ## Register online. No sales call, no procurement dance. New organizations are activated at once or reviewed first, depending on platform capacity. If yours is reviewed, you get an email when it is approved. # Privacy Policy Last updated October 12, 2026 > Template text: This page ships with the template. Replace the bracketed placeholders, adapt it to what your app really does and have it reviewed before launch. It is not legal advice. This policy explains what [Company name] collects when you use this app, why we collect it and the choices you have. ## Who is responsible [Company name], [Postal address], is responsible for your personal data. Contact us at [privacy@your-domain.example]. ## What we collect Account data such as your name, email address, password hash, passkeys and two-factor settings. Content you create, such as organizations, todos and uploaded files. Technical data such as IP address, browser, sessions and security events in the audit log. ## Why we use it To provide and secure the service, to send account emails such as verification, password reset and invitations, to prevent abuse and to meet legal obligations. We do not sell personal data. ## Cookies and local storage Essential cookies keep you signed in and remember your language. Your theme and cookie choices are stored in your browser. Analytics or marketing tools, if enabled, load only after you consent in the cookie banner, and you can change that choice at any time. ## Service providers We use processors that act on our instructions: Cloudflare for hosting, email and file storage, Neon for the database, and any payment or notification provider we enable. ## AI agents you connect If you connect an AI agent over MCP, it can read your data and propose drafts only within the scopes you approve. You can revoke its access at any time under Integrations. ## How long we keep data We keep account data while your account exists. When you delete your account in Settings, we delete your personal data within [30] days unless the law requires us to keep it. Security logs are kept for [90] days. ## Your rights Depending on where you live, you can access, correct, export or delete your data, object to its processing and complain to a data protection authority. Write to [privacy@your-domain.example] and we will answer within one month. ## Changes to this policy We post changes on this page and update the date at the top. For material changes we also notify you by email or in the app. # Terms of Service Last updated October 12, 2026 > Template text: This page ships with the template. Replace the bracketed placeholders, adapt it to what your app really does and have it reviewed before launch. It is not legal advice. These terms govern your use of the app operated by [Company name]. By creating an account you agree to them. ## Your account Give accurate information, keep your password and passkeys safe, and tell us at [privacy@your-domain.example] if you think your account was compromised. You are responsible for activity under your account. ## Acceptable use Do not break the law, infringe the rights of others, upload malware, probe or overload the service, or try to access data you are not allowed to see. ## Your content You keep ownership of what you upload. You give us the permission we need to store, process and display it in order to provide the service. Organization admins can manage content shared in their organization. ## Paid features If paid plans are offered, prices, billing periods and cancellation terms are shown before you buy and become part of these terms. ## Availability and changes We work to keep the service available but cannot guarantee it will be uninterrupted. We may change or discontinue features and will give notice of material changes. ## Ending your use You can delete your account at any time in Settings. We may suspend or close accounts that break these terms. ## Liability The service is provided as is. To the extent the law allows, [Company name] is not liable for indirect or consequential damages. Nothing in these terms limits liability that the law does not allow us to limit. ## Governing law These terms are governed by the laws of [Country or state]. ## Contact Questions about these terms go to [privacy@your-domain.example]. # Public demo posts ## Hello from the edge https://origin.its-live.dev/posts/hello-edge Ada Lovelace, 2026-06-01 Why we built this template on Cloudflare Workers. This is a demo post used to showcase dynamic OG images. ## End-to-end type-safe RPC https://origin.its-live.dev/posts/type-safe-rpc Alan Turing, 2026-06-10 oRPC ties the API and the client together. Another demo post for the template. # Public demo profiles ## Ada Lovelace https://origin.its-live.dev/u/ada Building on the edge. ## Alan Turing https://origin.its-live.dev/u/alan Type-safety enthusiast. # Create an image Turn an instance's root disk into your own image - clear its machine-id, snapshot and protect the volume, create the image - and update or delete it later. Create your own image to launch more instances with the same software and configuration as one you’ve already set up. You snapshot the instance’s root disk, protect the snapshot, and create an image from it. ## Before you begin [#before-you-begin] - An instance whose root disk holds what you want in the image. - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). ## Prepare the instance [#prepare-the-instance] 1. Log in to the instance and clear its machine-id, so every instance launched from the image generates its own: ```sh sudo truncate -s 0 /etc/machine-id sudo rm -f /var/lib/dbus/machine-id ``` If you skip this, every instance from the image shares one machine-id, which breaks VXLAN networking between them. See [Guest environment](/docs/compute/instances/guest-environment). 1. Stop the instance, so the snapshot captures a cleanly shut-down file system. See [Stop and start an instance](/docs/compute/instances/stop-start). ## Snapshot the root disk [#snapshot-the-root-disk] 1. Find the root disk’s volume URN. In `volumeAttachments`, it’s the entry with `isRootDevice` set to `true`: ```sh origin compute get-instance --instance-urn ``` 1. Create a snapshot of that volume: ```sh origin storage create-snapshot --volume-urn ``` 1. Run `get-snapshot` until `status` reads `COMPLETED`. Note its `volumeSizeInGib`: ```sh origin storage get-snapshot --snapshot-urn ``` 1. Protect the snapshot. Only a protected snapshot can back an image: ```sh origin storage protect-snapshot --snapshot-urn ``` 1. Run `get-snapshot` until `protectionStatus` reads `PROTECTED`. For more about snapshot states, see [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect). ## Create the image [#create-the-image] ```sh origin compute create-image \ --project-urn \ --root-device-snapshot-urn \ --root-device-size \ --description "Web server base" ``` - The snapshot must be in the project you create the image in. A snapshot of another project is refused as not found. - `--root-device-size` must be at least the snapshot’s `volumeSizeInGib`. It defaults to 8 GiB, so set it when the volume was larger. Instances launched from the image get a root disk of at least this size. - `--default-user` sets the account instances log in as. Omitted, it’s `cloud`. See [Guest environment](/docs/compute/instances/guest-environment). - `--root-device-name` sets the guest device name of the root disk. It defaults to `vda`. Names run from `vda` to `vdz`, without `/dev/`, and `vdc` is reserved. Any other value is refused, naming the field. Then check the result: 1. Verify the image. It reads `status: AVAILABLE`: ```sh origin compute get-image --image-urn ``` 1. Launch an instance from it to test it. See [Launch an instance](/docs/compute/instances/launch). With the API, `createImage` takes the root device as one of a list of `blockDeviceSpecs`, each with a `deviceName`, `snapshotUrn` and `sizeInGib`. `rootDeviceName` must name one of them. ## What keeping an image costs [#what-keeping-an-image-costs] An image keeps two billed resources alive for as long as you use it: - **The snapshot behind it.** Completed snapshots are billed for the size of the volume they were taken from, and the snapshot must stay protected for the image’s whole life. Once you unprotect or delete it, launches from the image are refused, although the image still reads `AVAILABLE`. - **The source volume.** A volume can’t be deleted while any of its snapshots exists, so the root disk you snapshotted stays billed too. To remove everything, work in this order: delete the image, unprotect and delete the snapshot, then delete the volume. See [Pricing](/docs/pricing) for the rates. ## Update or delete an image [#update-or-delete-an-image] The description is the only field you can change: ```sh origin compute update-image \ --image-urn \ --description "Web server base, hardened" ``` To delete an image: ```sh origin compute delete-image --image-urn ``` Deleting an image doesn’t affect instances already launched from it, because each has its own copy on its root disk. The snapshot behind the image isn’t deleted. Unprotect and delete it separately when you no longer need it. See [Delete a snapshot](/docs/storage/snapshots/delete). You can update and delete only your own images, not platform-provided ones. ## Related [#related] - [`create-image` reference](/docs/compute/reference/cli#create-image) - [Images](/docs/compute/images) - [Snapshots](/docs/storage/snapshots) # Image families How an image family resolves to its current platform-provided image, what its metadata tells you about upstream support, and what happens when one is withdrawn. An image family is a stable name for a line of platform-provided images, such as `ubuntu-22-04-minimal`. A launch that names a family gets whichever image the platform has designated as current for it. A launch that names an image URN gets exactly that image until you change it. Launch by family to pick up rebuilt images automatically. Launch by image URN to pin the image you tested against. ## Launching by family [#launching-by-family] The `launchInstance` mutation accepts `imageFamily` in place of `imageUrn`. Set exactly one of the two. The `origin compute launch-instance` command has no family option and takes `--image-urn` only. To find a family’s current image for the CLI, query images through the API and pick the platform-provided image whose `family` matches and whose `isFamilyCurrent` is `true`, then launch by its URN. You can make the same pick from the output of `origin compute list-images`, which includes `family` and `isFamilyCurrent` for platform-provided images. For example, with `jq`: ```sh origin compute list-images --project-urn \ | jq -r '.. | objects | select(.family? == "" and .isFamilyCurrent? == true) | .urn' ``` Pass the printed URN to `launch-instance` as `--image-urn`. The CLI help for `list-image-families` mentions an `--image-family` option, but `launch-instance` doesn’t accept one. A family resolves separately per CPU architecture. With `X86_64` as the only architecture, a family resolves to one image. A new image is published into a family first and designated current afterward, so a family can briefly have a newer image that isn’t current yet. A family that has no current image refuses launches with “no image is currently published for this family”. ## Family metadata [#family-metadata] Read the families with the `imageFamilies` query or `origin compute list-image-families`. No permission is needed. | Field | Meaning | | --- | --- | | `slug` | The name to pass as `imageFamily`, for example `ubuntu-22-04-minimal`. | | `vendor` | Who publishes the upstream release, for example `Canonical`. | | `os` | The operating system the family tracks, for example `ubuntu`. | | `osVersion` | The release, for example `22.04`. | | `description` | A human-readable description. | | `supportEndsAt` | When the upstream vendor stops supporting this release, if a date is known. | `supportEndsAt` is advisory. No launch is refused on it, and running instances aren’t affected. Treat it as notice to move to a newer family. ## Stable names and withdrawn families [#stable-names-and-withdrawn-families] A family is never renamed, and a name is never reused for a different line. A name in your scripts keeps meaning what it meant. A family can be withdrawn when a newer line supersedes it. A withdrawn family: - Drops out of `imageFamilies` and `list-image-families`. - Refuses launches by its name, with `image family '' is retired and launches nothing`. - Doesn’t affect anything you’re already running. The images published under it stay listed and can still be launched by URN. ## Related [#related] - [Images](/docs/compute/images) - [Launch an instance](/docs/compute/instances/launch) - [`list-image-families` reference](/docs/compute/reference/cli#list-image-families) # Images An image is what an instance boots from. Learn the difference between platform-provided and your own images, and what each image field means. An image is the template an instance boots from: the operating system and whatever else was built into it. You choose one at launch. The launch copies the image onto the new instance’s root disk, and from then on the instance doesn’t depend on the image. The following table shows where images come from and how they’re used. | From | Step | To | | --- | --- | --- | | Image family | resolves to | Platform-provided image | | Volume | snapshot | Protected snapshot | | Protected snapshot | `create-image` | Your image | | Platform-provided image | launch | Instance | | Your image | launch | Instance | ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Platform-provided image | An image the platform publishes, such as a Debian or Ubuntu base image. Any project can launch from one. It lists alongside your own images in `list-images`. | | Your own image | An image you create from a protected snapshot of one of your volumes. It belongs to the project you create it in. See [Create an image](/docs/compute/images/create). | | Image family | A stable name for a line of platform-provided images that resolves to the current one. See [Image families](/docs/compute/images/image-families). | | Default user | The account an instance launched from the image logs in as. Every image has a `defaultUser`. The platform-provided images use `cloud`. See [Guest environment](/docs/compute/instances/guest-environment). | Your own image depends on the snapshot it was built from for its whole life. The platform doesn’t check whether an image uses the snapshot. Once you unprotect or delete that snapshot, launching instances from the image is refused, although the image still reads `AVAILABLE`. See [Delete a snapshot](/docs/storage/snapshots/delete). ## Image fields [#image-fields] Three image fields are typed enums in the API. Each has exactly one value. Handle the value you get, and let a value your client doesn’t recognize surface rather than defaulting it away. | Field | Value | Meaning | | --- | --- | --- | | `status` | `AVAILABLE` | The image can be launched from. An image becomes visible only once its contents are in place, and there is no other status. An image that couldn’t be created never appears. | | `architecture` | `X86_64` | The CPU architecture the image’s contents are built for. An instance launched from it runs on a machine of that architecture. | | `platform` | `LINUX_UNIX` | The operating-system family. It covers every Linux and UNIX-like distribution. | Platform-provided images also carry `family`, the family they belong to, and `isFamilyCurrent`, whether the family currently resolves to that image. ## What you can do [#what-you-can-do] - [Create an image](/docs/compute/images/create) from one of your volumes - List images with [`origin compute list-images`](/docs/compute/reference/cli#list-images) and read one with [`origin compute get-image`](/docs/compute/reference/cli#get-image) - [Launch an instance](/docs/compute/instances/launch) from an image ## Related [#related] - [Image families](/docs/compute/images/image-families) - [Snapshots](/docs/storage/snapshots) - [origin compute commands](/docs/compute/reference/cli) # What is Origin Cloud Compute? Compute runs virtual machines on Origin Cloud. Learn how instances, images, instance types and key pairs fit together and how to reach them. Compute runs virtual machines, called instances, without you owning or operating the hardware underneath. You pick an image to boot from, an instance type for its size and a key pair to log in with. The platform creates the instance's root disk and network interface, places it on a machine and starts it. You can stop an instance, start it again later, change its size while it's stopped, or terminate it for good. The image provides the operating system. The instance type sets vCPU and memory. The key pair's public key is installed for the login user. Volumes hold the instance's data and live in the [Storage guide](/docs/storage). The network interface and its security groups belong to the [Network guide](/docs/network). ## Features [#features] - **Instances**: Virtual machines with a lifecycle you control, health checks that report what the platform observes, and defined behavior when a machine fails. See [Instances](/docs/compute/instances). - **Instance storage**: Every instance boots from a durable root disk you can size at launch. You can attach and detach more volumes while the instance runs. See [Instance storage](/docs/compute/instance-storage). - **Images**: Platform-provided images and image families, plus your own images made from a snapshot of a volume. See [Images](/docs/compute/images). - **Key pairs**: SSH key pairs you import or have the platform generate. The public half goes into every instance you launch with it. See [Key pairs](/docs/compute/key-pairs). ## Ways to access Compute [#ways-to-access-compute] - **CLI**: The `origin compute` command group. See [CLI access](/docs/platform/access/cli) to install and sign in, and [origin compute commands](/docs/compute/reference/cli) for every command. - **GraphQL API**: Instances, images, image families, instance types and key pairs live under the `compute` namespace of the API, for both queries and mutations. See [API access](/docs/platform/access/api). - **Origin Cloud console**: The web interface at [console.origincloud.eu](https://console.origincloud.eu), for working with your instances in a browser. These docs cover the CLI and the API. ## When to use Compute [#when-to-use-compute] Use Compute when you need a general-purpose Linux machine you administer yourself: a web server, a build agent, a database you operate, or the nodes of your own Kubernetes cluster. You get full root access through `sudo`, a durable root disk and a private network. Compute doesn't restart an instance for you after a machine failure. If a workload must keep serving through the loss of one machine, run more than one instance. For more information, see [When the machine under an instance fails](/docs/compute/instances/host-failure). ## Related services [#related-services] - [Storage](/docs/storage): volumes and snapshots that hold instance data - [Network](/docs/network): VPCs, subnets, security groups and floating IPs that connect instances - [Platform](/docs/platform): organizations, projects, billing and access ## Pricing [#pricing] An instance's compute usage is billed while it is `RUNNING`. Its volumes are billed while they exist, including while the instance is stopped. For prices, see [Pricing](/docs/pricing). ## Next steps [#next-steps] - [Get started with Origin Cloud](/docs/platform/getting-started) - [Launch an instance](/docs/compute/instances/launch) - [Compute reference](/docs/compute/reference): every command and status reason - [Troubleshoot Compute](/docs/compute/troubleshooting) # Attach and detach volumes Attach an available volume to a running or stopped instance, choose its guest device name, and detach it again to use elsewhere. Attach a volume to give an instance another disk. Detach it to move the disk and its data to another instance. The instance can be running or stopped. ## Before you begin [#before-you-begin] - An instance in `RUNNING` or `STOPPED`. - A volume in `AVAILABLE` status, in the same project and availability zone as the instance. See [Create a volume](/docs/storage/volumes/create). - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). ## Attach a volume [#attach-a-volume] 1. Attach the volume: ```sh origin compute attach-volume \ --instance-urn \ --volume-urn ``` To choose the guest device name, add `--device-name`, for example `--device-name vdb`. Names run from `vda` to `vdz`, and `vdc` is reserved by the platform. Omitted, the platform assigns the first free name. 1. Check the attachment in the instance’s `volumeAttachments`: ```sh origin compute get-instance --instance-urn ``` - On a stopped instance, the attachment reads `ATTACHED` right away and the disk appears in the guest at the next start. - On a running instance, the disk is added live. The attachment reads `ATTACHING`, then `ATTACHED` once the guest sees the device. If the device can’t be added, it reads `FAILED` and the volume is released. 1. Verify inside the guest that the disk is there, under the attachment’s `deviceName`: ```sh lsblk ``` A new volume has no file system. Create one before you mount it. ## Detach a volume [#detach-a-volume] 1. Unmount the file system inside the guest if the instance is running. 1. Detach the volume: ```sh origin compute detach-volume \ --instance-urn \ --volume-urn ``` On a running instance the attachment reads `DETACHING` until the guest releases the device. If the guest doesn’t release it, the attachment returns to `ATTACHED` and the volume stays attached. 1. Verify that the volume reads `AVAILABLE`: ```sh origin storage get-volume --volume-urn ``` The attachment stays in the instance’s `volumeAttachments` history as `DETACHED`, with its volume reference cleared. You can’t detach an instance’s root disk. ## Using the API [#using-the-api] The `attachVolume` and `detachVolume` mutations return the attachment: ```graphql mutation { compute { attachVolume(input: { instanceUrn: "" volumeUrn: "" deviceName: "vdb" }) { urn deviceName status } } } ``` ## If this fails [#if-this-fails] An attach is refused when the instance is neither running nor stopped, when the volume isn’t `AVAILABLE`, or when the device name you asked for is already taken. To find which instance holds a volume that reads `INUSE`, see [Find the instance that holds a volume](/docs/storage/volumes/find-instance). ## Related [#related] - [`attach-volume` reference](/docs/compute/reference/cli#attach-volume) - [`detach-volume` reference](/docs/compute/reference/cli#detach-volume) - [Instance storage](/docs/compute/instance-storage) # Instance storage How an instance's durable root disk is created and sized at launch, and how extra volumes attach to a running or stopped instance. Every instance boots from a root disk that the launch creates from the image. On top of that, you can attach volumes you created yourself. All of an instance’s volumes are durable network storage that isn’t tied to any machine, so an instance can stop, start and move between machines without losing data. The following table shows where an instance’s disks come from. | From | Step | To | | --- | --- | --- | | Image | launch copies | Root disk of the instance | | Volume you created | attach | Instance | | Instance | detach | Volume you created | ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Root disk | The volume the instance boots from. The launch creates it by copying the image onto it. It can’t be detached, and it’s deleted when the instance terminates. | | Attached volume | A volume you created and attached. It outlives the instance: termination releases it rather than deleting it. See [Attach and detach volumes](/docs/compute/instance-storage/attach-detach). | | Storage backend | Instance volumes use the `pvs` backend: durable, network-attached storage. A launch that asks for `host_local` is refused immediately, naming the field, and creates nothing. | ## Sizing the root disk [#sizing-the-root-disk] By default the root disk is exactly as large as the image, which for a platform-provided image is enough for the operating system and little else. Ask for more at launch with `bootVolume` on `launchInstance`, or `--boot-volume-size-gib` and `--boot-volume-storage-class` on `origin compute launch-instance`. Size and storage class are independent, and both are optional. - **The image’s size is the minimum.** A smaller size is refused rather than raised. The error names the field and the smallest size that works. - **You get and pay for exactly the size you ask for.** Most images grow their root file system to fill the disk on first boot. That behavior belongs to the image, so check inside the guest if it matters. - **The storage class is checked against the live catalog.** Read it with `origin storage list-storage-classes` or the `pvs.storageClasses` query, and pick one whose `available` is `true`. A class that doesn’t exist is refused as invalid input. One that exists but isn’t on sale is refused with `PRODUCT_UNAVAILABLE`. See [Storage classes](/docs/storage/volumes/storage-classes). - **It counts against your storage quota at launch.** A launch that would take the organization or project past its volume storage limit is refused up front, naming the quota. See [Limits](/docs/platform/reference/limits). You can’t change the root disk’s storage class after launch. To grow it later, resize the volume, which only grows. See [Resize a volume](/docs/storage/volumes/resize). Both are reasons to ask for what you need at launch. ## What you can do [#what-you-can-do] - [Attach and detach volumes](/docs/compute/instance-storage/attach-detach) - [Launch an instance](/docs/compute/instances/launch) with a larger root disk - [Find which instance holds a volume](/docs/storage/volumes/find-instance) ## Limits and quotas [#limits-and-quotas] See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Volumes](/docs/storage/volumes) - [Snapshots](/docs/storage/snapshots) - [Images](/docs/compute/images) # Change an instance's type Change a stopped instance to a different instance type so it starts again with more or fewer vCPUs and memory, keeping its identity and volumes. Change an instance’s type to resize it, or to move it off a type that is no longer offered. Only the size changes. The instance keeps its URN, its addresses and its volumes. ## Before you begin [#before-you-begin] - An instance that you stopped and that reads `STOPPED`. A `FAILED` instance still holds capacity on its machine, so you can’t change its type. Start and stop it cleanly first, or terminate it. - Free vCPU quota if the new type is larger. Growing is checked against the same vCPU quota as a launch. Shrinking never is. See [Limits](/docs/platform/reference/limits). ## Change the type [#change-the-type] 1. Stop the instance if it’s running. See [Stop and start an instance](/docs/compute/instances/stop-start). 1. Pick a type whose `available` is `true`: ```sh origin compute list-instance-types ``` 1. Change the type: ```sh origin compute change-instance-type \ --instance-urn \ --instance-type gp1.core.4 ``` 1. Verify the change. `instanceType` on the instance now reads the new type: ```sh origin compute get-instance --instance-urn ``` 1. Start the instance: ```sh origin compute start-instance --instance-urn ``` ## Using the API [#using-the-api] ```graphql mutation { compute { changeInstanceType(input: { instanceUrn: "" instanceType: "gp1.core.4" }) { accepted message } } } ``` ## If this fails [#if-this-fails] - [`PRODUCT_UNAVAILABLE`](/docs/platform/reference/errors#product_unavailable): the type you named is no longer offered. Pick one whose `available` is `true`. See [Instance types](/docs/compute/instances/instance-types). - Quota exceeded: the larger type would take the organization or project past its vCPU limit. Choose a smaller type or request a higher limit. - The instance isn’t stopped: stop it first and wait for `STOPPED`. ## Related [#related] - [`change-instance-type` reference](/docs/compute/reference/cli#change-instance-type) - [Instance types](/docs/compute/instances/instance-types) # Guest environment What the platform sets up inside an instance at first boot - the login user and SSH key, time synchronization - and why each image needs its own machine-id. At first boot, the platform hands the guest a short configuration through cloud-init. It creates the login user with your SSH key and points the guest’s clock at the platform’s time service. Everything else inside the guest comes from the image. You can’t pass your own user data (a cloud-init configuration or script) at launch, and instances can’t be given names or labels. To start instances with your own configuration, build it into an image. See [Create an image](/docs/compute/images/create). To tell instances apart, keep your own record of which URN is which. ## Login user [#login-user] Every instance has a login user: a non-root account with passwordless sudo and no password of its own. The public key of the instance’s key pair is its only credential, so the login is `ssh @
`. The name comes from one of two places: - **The image’s `defaultUser`.** Every image carries one. The platform-provided images use `cloud`. When you create your own image you can set a different one. See [Images](/docs/compute/images). - **A `loginUser` override at launch.** Set `loginUser` on `launchInstance`, or `--login-user` on `origin compute launch-instance`, to use a different name for one instance without publishing an image for it. A login user name is a POSIX user name: lowercase letters, digits, underscores and hyphens, at most 32 characters, starting with a letter or underscore, and not `root`. Whichever applies, the instance reports it as `loginUser`. Read the name from the instance rather than from the image. It’s fixed for the instance’s life, even if the image is later deleted or its family moves on. ## Time synchronization [#time-synchronization] Instances keep their clocks synchronized without anything to install or open up. The platform serves time on the same address inside your subnet that answers DNS, and configures the guest’s `systemd-timesyncd` to use it at first boot. An instance with no floating IP and no route to the internet still keeps accurate time. A drifting clock surfaces late and looks unrelated: TLS certificates that seem expired or not yet valid, tokens rejected as stale, clustered software disagreeing about order, and logs that don’t line up across instances. To confirm synchronization inside a running instance, run: ```sh timedatectl ``` Expect `NTP service: active` and `System clock synchronized: yes`. You can point the guest at your own time source instead, like on any Linux machine. Reaching a time server outside your VPC needs internet access, so an instance without a floating IP or a NAT gateway can only use the platform’s. See [Internet access](/docs/network/internet-access). ### Host clock trust [#host-clock-trust] The time an instance receives comes from the physical machine it runs on. If that machine’s own clock isn’t synchronized, the platform tells the guest so instead of passing bad time off as good. The guest then declines to sync and reports `System clock synchronized: no`. That’s the safe direction, but it means an unsynchronized clock can be a platform problem rather than yours. If `System clock synchronized: no` persists on an instance that uses the platform’s time service, contact Origin Cloud support. ## Machine identity [#machine-identity] A Linux instance’s machine-id (`/etc/machine-id`) comes from its image. The platform-provided images ship it empty, so each instance generates its own on first boot. An image you create from a volume contains the machine-id of the instance that volume belonged to. Every instance launched from that image starts with the same machine-id. Clear it before you snapshot the volume. For the steps, see [Create an image](/docs/compute/images/create). Two instances that share a machine-id break in a way you’re likely to hit. systemd derives the MAC address of virtual network devices from the machine-id, so same-named VXLAN devices on both instances get the same MAC address and can’t exchange packets. That’s what Kubernetes pod networking with VXLAN or Geneve encapsulation looks like when it fails this way. Run `cat /etc/machine-id` on both instances first. ## Related [#related] - [Key pairs](/docs/compute/key-pairs) - [Images](/docs/compute/images) - [Launch an instance](/docs/compute/instances/launch) - [Troubleshoot Compute](/docs/compute/troubleshooting) # Instance health checks What each instance health check observes, how results combine into availability, and how the category tells you whether a problem is yours to fix. `status` tells you what was asked for. Health checks tell you what the platform can observe right now. You need both: an instance whose machine has become unreachable is still `RUNNING`, because nothing stopped it. Read `healthChecks` on an instance for a result per check and an availability summary. | What you see | What it means | What to do | | --- | --- | --- | | `availability` is `AVAILABLE` | The platform observes nothing wrong with the guest. | Nothing. It doesn’t prove your application is up; monitor that yourself. | | A `SYSTEM` check is `IMPAIRED`, or checks read `INSUFFICIENT_DATA` | The platform underneath your instance has a problem, or has lost sight of the machine. | Nothing to fix inside the instance. If it persists, contact Origin Cloud support. | | An `INSTANCE` check is `IMPAIRED` | Your instance’s own operating system or network configuration has a problem. | Fix it inside the instance. Waiting won’t fix it. If it’s `GUEST_PRESENT`, stop and start the instance. | The sections below explain each check and how the summary is built. ```graphql query { compute { instance(instanceUrn: "") { status healthChecks { availability checks { kind category status since } } } } } ``` `since` is when the check entered its current result. It’s `null` while nothing has observed the check. ## Checks [#checks] Every check is always present in `checks`. A check with nothing to report says so rather than being left out. | `kind` | `category` | What it observes | | --- | --- | --- | | `HOST_REACHABLE` | `SYSTEM` | Whether the platform can reach the machine carrying the instance. | | `DOMAIN_STATE` | `INSTANCE` | What the machine reports about the virtual machine. `OK` only when it reports the virtual machine running. Paused or crashed reads `IMPAIRED`. | | `NETWORK_REACHABLE` | `INSTANCE` | Whether the guest’s network stack answers. See [Network reachability](#network-reachability). | | `GUEST_AGENT` | `INSTANCE` | A report from an agent inside the guest. Always `NOT_APPLICABLE`, because the platform’s images ship no such agent. | | `GUEST_PRESENT` | `INSTANCE` | Whether the machine carrying the instance still has it. See [When `GUEST_PRESENT` is `IMPAIRED`](#when-guest_present-is-impaired). | New kinds can appear in the enum. Ignore a kind your client doesn’t recognize rather than failing on it. ## Results [#results] Each check reports one of four results: | Result | Meaning | | --- | --- | | `OK` | The check ran and the instance passed. | | `IMPAIRED` | The check ran and the instance failed it. | | `INSUFFICIENT_DATA` | The platform could not tell, most often because the machine carrying the instance has stopped reporting. Treat it as unknown, not as healthy. | | `NOT_APPLICABLE` | The check doesn’t apply. Every check reads `NOT_APPLICABLE` while the instance is `STOPPING`, `STOPPED`, `SHUTTING_DOWN` or `TERMINATED`, because there is no guest to observe. | A result that isn’t refreshed for 120 seconds goes back to `INSUFFICIENT_DATA`. The platform doesn’t keep showing a value it can no longer confirm. ## Availability [#availability] `availability` combines the checks into one value for a listing: | `availability` | When | | --- | --- | | `IMPAIRED` | At least one check is `IMPAIRED`. | | `UNKNOWN` | No check is `IMPAIRED`, and at least one is `INSUFFICIENT_DATA`. | | `NOT_APPLICABLE` | Every check is `NOT_APPLICABLE`. | | `AVAILABLE` | Every other case: no check is `IMPAIRED` or `INSUFFICIENT_DATA`, and at least one is `OK`. | `NOT_APPLICABLE` doesn’t hold the summary down, so a healthy running instance reads `AVAILABLE` even though `GUEST_AGENT` is `NOT_APPLICABLE`. `INSUFFICIENT_DATA` does, so the summary never rounds an unknown up to `AVAILABLE`. ## Categories [#categories] The `category` on each check tells you who has to act: | Category | Who has to act | | --- | --- | | `SYSTEM` | The platform underneath your instance. There is nothing to fix inside the instance. If it persists, contact Origin Cloud support. | | `INSTANCE` | Your instance’s own operating system and network configuration. Waiting won’t fix it. | If you only read `availability`, you lose this distinction. Read the checks when the summary isn’t `AVAILABLE`. ## Network reachability [#network-reachability] `NETWORK_REACHABLE` never reports an instance unhealthy only because it’s quiet. Traffic the guest sends counts as proof it’s alive. When the guest has sent nothing, the platform asks it directly with an IPv6 neighbor solicitation, which the guest’s kernel answers without any agent. The check reads `IMPAIRED` only after three consecutive probes go unanswered, about 90 seconds of silence. The check tells you the guest’s operating system and network stack are up. It doesn’t tell you your application is. A crashed service inside a healthy guest doesn’t show up here. Use your own monitoring for that. ## When the machine stops reporting [#when-the-machine-stops-reporting] When the platform loses contact with the machine carrying your instance, `HOST_REACHABLE` reads `IMPAIRED`. The instance-level checks stop being refreshed and read `INSUFFICIENT_DATA` within 120 seconds. Once the reachability result itself ages out, every check reads `INSUFFICIENT_DATA` and `availability` reads `UNKNOWN`. Read that as “the platform has lost sight of this instance”, not “this instance has stopped”. The platform can’t tell which, and it doesn’t claim either. The instance’s `status` stays `RUNNING`. For what happens if the machine has failed, see [When the machine under an instance fails](/docs/compute/instances/host-failure). ## When GUEST_PRESENT is IMPAIRED [#when-guest_present-is-impaired] `GUEST_PRESENT` reading `IMPAIRED` means the machine carrying your instance is up and reporting, and your instance is no longer running on it. That differs from an `IMPAIRED` `DOMAIN_STATE`, which describes a virtual machine that still exists but isn’t running properly. The platform reports it only after the machine has given a complete account of what it runs and left your instance out for 60 seconds. A machine that’s merely unreachable never produces it. In the same state, `HOST_REACHABLE` reads `OK`. This is the one check that asks you to act. The instance’s `status` stays `RUNNING`, because nobody asked for anything else. Stop the instance and start it again. The stop completes quickly, since there is nothing left to shut down. The start can place the instance on any machine, with its volumes, network interface and addresses unchanged. To automate this, poll `healthChecks` and act on `GUEST_PRESENT: IMPAIRED`. ## Related [#related] - [Instance lifecycle](/docs/compute/instances/lifecycle) - [When the machine under an instance fails](/docs/compute/instances/host-failure) - [Stop and start an instance](/docs/compute/instances/stop-start) - [Troubleshoot Compute](/docs/compute/troubleshooting) # When the machine under an instance fails What happens to an instance when its physical machine fails or is taken out of service, what survives, and why restarting it is your decision. The machines your instances run on can fail, for example through a component fault or a loss of power. When the machine carrying your instance goes down, your instance goes down with it. The platform records that once it can prove it, and leaves restarting the instance to you. The following diagram shows how an instance’s status and health change after its machine fails. | From | Event | To | | --- | --- | --- | | `RUNNING` | Machine stops answering | `RUNNING`, `HOST_REACHABLE` impaired | | `RUNNING`, `HOST_REACHABLE` impaired | Machine restart proven | `STOPPED` | | `RUNNING`, `HOST_REACHABLE` impaired | Machine taken out of service | `STOPPED` | | `RUNNING` | Machine restart proven | `STOPPED` | | `STOPPED` | You start it | `PENDING` | ## While the machine is unreachable [#while-the-machine-is-unreachable] A machine the platform can’t reach proves nothing about what runs on it. So the instance stays `RUNNING`, `HOST_REACHABLE` reads `IMPAIRED`, and the other checks fall back to `INSUFFICIENT_DATA`. For how to read that, see [Instance health checks](/docs/compute/instances/health-checks). ## When the platform records the failure [#when-the-platform-records-the-failure] The platform moves the instance from `RUNNING` straight to `STOPPED`, without `STOPPING`, in two cases: - The machine restarted. The machine comes back and the platform can prove it restarted. A virtual machine doesn’t survive that. `statusReason` reads: `the machine this instance was running on failed, and the instance went down with it; start it again to bring it back`. - The machine is taken out of service. The machine doesn’t come back, and the platform takes it out of service after confirming it’s powered off. `statusReason` reads: `the machine this instance was running on failed and has been taken out of service; the instance went down with it, and starting it again will place it on another machine`. From that moment the instance uses no compute capacity and accrues no compute usage, exactly as if you had stopped it. Its network interface stays reserved and its volumes stay attached. ## Starting it again is up to you [#starting-it-again-is-up-to-you] The platform doesn’t start the instance again for you. Whether a workload should come back on its own after a failure, or needs checking first, depends on the workload. Starting it is an ordinary start. Its volumes, network interface, addresses and security groups are as they were, and it can come up on a different machine. If your workload should come back on its own, watch for `STOPPED` with a non-null `statusReason` and start the instance. For the steps, see [Stop and start an instance](/docs/compute/instances/stop-start). The status reason says “start it again to bring it back”, and a start usually does. After a start, check that the guest really answers, not only that the instance reads `RUNNING` and `AVAILABLE`: connect to it, or query its CPU metric. If it stays unreachable, see [Running and available after a machine failure, but unreachable](/docs/compute/troubleshooting#running-and-available-after-a-machine-failure-but-unreachable). ## What survives [#what-survives] | Outcome | What | | --- | --- | | Survives | Everything on the instance’s volumes. Volumes aren’t tied to a machine, so they come back attached to the same instance with the same contents. Nothing is rebuilt from the image. The instance URN, network interface, private and public addresses, and security groups also stay the same. | | Doesn’t survive | Anything only in memory, and anything on a temporary file system. Treat a machine failure the way you’d treat a sudden power loss. | ## Planned moves [#planned-moves] When a machine needs maintenance, the platform can move the instances on it to another machine. Moving an instance means stopping it and starting it again elsewhere. From inside the guest, that looks like a reboot you didn’t ask for. In the API, the instance passes through `STOPPING`, `STOPPED` and `PENDING` back to `RUNNING`, with the same volumes, interface and addresses. If your workload can’t tolerate an unannounced restart, run more than one instance and spread the load across them. A move affects the instances on one machine, so an instance on another machine keeps serving. ## Related [#related] - [Instance health checks](/docs/compute/instances/health-checks) - [Instance lifecycle](/docs/compute/instances/lifecycle) - [Status reasons](/docs/compute/reference/status-reasons) # Instances An instance is a virtual machine on Origin Cloud. Find its lifecycle, types, health checks, failure behavior and the tasks to launch and manage one. An instance is a virtual machine. It boots from an image, runs with the vCPU and memory of its instance type, and keeps its identity, addresses and volumes for its whole life, across stops and starts. You decide when it runs. The platform reports both what you asked for (`status`) and what it can observe (`healthChecks`). The following diagram shows the main path through an instance’s life. The full set of eight statuses, including `FAILED`, is on [Instance lifecycle](/docs/compute/instances/lifecycle). ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Lifecycle | The eight statuses an instance moves through, which ones resolve on their own, and which ones you’re billed for. See [Instance lifecycle](/docs/compute/instances/lifecycle). | | Instance type | The size of an instance: its vCPU count and memory, from a catalog of types. See [Instance types](/docs/compute/instances/instance-types). | | Health checks | What the platform observes about a running instance, separate from its status, and whether a problem is the platform’s or yours. See [Instance health checks](/docs/compute/instances/health-checks). | | Machine failure | What happens to an instance when the physical machine under it fails or is taken out of service. See [When the machine under an instance fails](/docs/compute/instances/host-failure). | | Guest environment | What the platform sets up inside the guest: the login user, time synchronization and machine identity. See [Guest environment](/docs/compute/instances/guest-environment). | ## What you can do [#what-you-can-do] - [Launch an instance](/docs/compute/instances/launch) - [Stop and start an instance](/docs/compute/instances/stop-start) - [Change an instance’s type](/docs/compute/instances/change-type) - [Terminate an instance](/docs/compute/instances/terminate) ## Limits and quotas [#limits-and-quotas] Launching an instance counts against your instance-count and vCPU quotas, at both the organization and the project level. See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Instance storage](/docs/compute/instance-storage) – the root disk and extra volumes - [Images](/docs/compute/images) – what an instance boots from - [Key pairs](/docs/compute/key-pairs) – how you log in - [Security groups](/docs/network/traffic-control/security-groups) – what traffic reaches an instance - [origin compute commands](/docs/compute/reference/cli) # Instance types How instance types set an instance's vCPU and memory, how type names are built, and how to read the live catalog and its available flag. An instance type sets an instance’s vCPU count and memory. You choose one at launch, and you can change it later while the instance is stopped. A running instance keeps the size it has. ## Type names [#type-names] A type name has three parts, for example `gp1.core.2`: | Part | Meaning | | --- | --- | | Kind | The first part, such as `gp1`. A kind is a hardware family. Instances of one kind only run on machines built for that kind. | | Profile | The middle part, such as `core`. It describes the type’s memory and network profile. | | Size | The last part, the vCPU count. | Don’t derive vCPU or memory from the name. Each type in the catalog states both. ## Types on sale [#types-on-sale] On 13 October 2026, these types were on sale, at these list prices (EUR excluding VAT). The catalog and the [price list](/docs/pricing) are the live source: check `available` and each type’s `vcpu` and `memoryMib` there before you launch. | Instance type | List price per hour | About per month (730 hours) | | --- | --- | --- | | `gp1.core.2` | €0.0551 | €40.22 | | `gp1.core.4` | €0.1103 | €80.52 | | `gp1.core.8` | €0.2205 | €160.97 | | `gp1.core.16` | €0.4410 | €321.93 | | `gp1.core.32` | €0.8821 | €643.93 | `gp1.core.2`, with 2 vCPUs and 8 GiB of memory, is the smallest. Each price is the price list entry `compute.gp1.core.`; see [Read the price list](/docs/pricing/read-price-list). ## The catalog [#the-catalog] The catalog lists every instance type the platform has. Read it with the `instanceTypes` query or with `origin compute list-instance-types`. No permission is needed, and the catalog is the same for every organization. Each entry carries these fields: | Field | Meaning | | --- | --- | | `instanceType` | The name to pass at launch, for example `gp1.core.2`. | | `kind` | The hardware family, for example `gp1`. | | `cpuAllocationMode` | The middle part of the name, for example `core`. | | `vcpu` | Number of vCPUs. | | `memoryMib` | Memory in MiB. | | `available` | Whether you can launch or change to this type right now. | ## Available and withdrawn types [#available-and-withdrawn-types] The catalog also lists types that are no longer offered, with `available: false`. They stay listed because an instance running as one still reports that type, and you need to be able to look it up. Filter on `available` before you pick a type. A withdrawn type affects instances like this: - Launch or change to it. Refused with `PRODUCT_UNAVAILABLE`. A type name that never existed is refused as invalid input instead. - A running instance of that type. Unaffected. It keeps its vCPU and memory. - A stopped instance of that type. Starting it is refused with `PRODUCT_UNAVAILABLE`, naming the type. The platform doesn’t start it at a different size on its own. Change it to an available type first. See [Change an instance’s type](/docs/compute/instances/change-type). ## Capacity [#capacity] A type in the catalog with `available: true` can still be refused at launch when no machine has room for it. The launch fails with `INSUFFICIENT_CAPACITY`, naming the type and what was short. Nothing is created. ## Related [#related] - [Launch an instance](/docs/compute/instances/launch) - [Change an instance’s type](/docs/compute/instances/change-type) - [Limits](/docs/platform/reference/limits) - [Pricing](/docs/pricing) The machine series page on origincloud.eu describes the families and the workloads each is built for. # Launch an instance Launch a virtual machine with the CLI or the API - choose an image, instance type, key pair, network and root disk - and log in over SSH. Launch an instance to get a running Linux machine you can log in to over SSH. You choose what it boots from, its size, its key pair and where it sits on the network. ## Before you begin [#before-you-begin] - An organization that is approved and has a valid payment method, and a project to launch into. See [Organizations](/docs/platform/organizations) and [Add a payment method](/docs/platform/billing/payment-method). The project’s URN is `urn:origin:cloud:admin::::`; see [Resource URNs](/docs/platform/access/api#resource-urns). - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). - A key pair in the project, and its URN from the `urn` field that `import-key-pair` or `generate-key-pair` printed. `origin compute list-key-pairs --project-urn ` lists it again. See [Create a key pair](/docs/compute/key-pairs/create). - Free quota for one more instance and its vCPUs, and for its root disk. See [Limits](/docs/platform/reference/limits). ## Launch the instance [#launch-the-instance] 1. Choose an instance type whose `available` is `true`: ```sh origin compute list-instance-types ``` For what the fields mean, see [Instance types](/docs/compute/instances/instance-types). 1. Choose an image. List the platform-provided images and your own: ```sh origin compute list-images --project-urn ``` To launch the current build of an image family instead, see [Using the API](#using-the-api). The CLI only launches by image URN. 1. Launch the instance: ```sh origin compute launch-instance \ --project-urn \ --image-urn \ --instance-type gp1.core.2 \ --key-pair-urn ``` With no `--subnet-urn`, the instance goes into your project’s default subnet. That subnet is created on first use, in a VPC with an internet gateway, and the instance’s network interface gets a public address automatically. See [Default VPC](/docs/network/vpcs/default-vpc). 1. Add the options you need. Each is optional: | Option | Use it to | | --- | --- | | `--subnet-urn ` | Place the instance in a subnet of your own VPC. | | `--security-group-urn ` | Attach security groups to the network interface. Repeat it for several groups. Omitted, the VPC’s default security group applies. You can’t change the interface’s groups after launch, only the rules inside them. See [Security groups](/docs/network/traffic-control/security-groups). | | `--boot-volume-size-gib ` | Make the root disk bigger than the image. See [Instance storage](/docs/compute/instance-storage). | | `--boot-volume-storage-class ` | Pick the root disk’s storage class. See [Storage classes](/docs/storage/volumes/storage-classes). | | `--login-user ` | Override the image’s default user. See [Guest environment](/docs/compute/instances/guest-environment). | `--volume-backend` accepts only `pvs`, which is the default. Leave it out. A launch takes no user data (cloud-init configuration of your own), and instances, volumes and network resources can’t be given names or labels. Build the configuration you need into your own image, see [Create an image](/docs/compute/images/create), and keep your own record of which URN is which. 1. Note the instance’s `urn` and `loginUser` in the response. The following steps use them. 1. Wait for the instance to reach `RUNNING`. Run `get-instance` until status stops changing: ```sh origin compute get-instance --instance-urn ``` It passes through `INITIALIZING` and `PENDING` first. If it ends up `FAILED`, read its `statusReason` and see [Status reasons](/docs/compute/reference/status-reasons). If the host never confirms the start, the instance can stay `PENDING` for about 30 minutes before it becomes `FAILED`. To poll every 10 seconds until the status stops changing, with `jq`: ```sh while :; do status="$(origin compute get-instance --instance-urn \ | jq -r '[.. | .status? | strings] | first')" echo "$status" case "$status" in RUNNING | STOPPED | FAILED | TERMINATED) break ;; esac sleep 10 done ``` 1. Find the instance’s public address. List the project’s floating IPs and their private addresses: ```sh origin network list-floating-ips --project-urn ``` To match a floating IP to the instance, list the network interfaces with `origin network list-network-interfaces --project-urn `. The interface whose `attachedToUrn` is your instance’s URN carries its private addresses. See [Network interfaces](/docs/network/vpcs/network-interfaces). To print the instance’s public address in one go, with `jq`: ```sh nic="$(origin compute get-instance --instance-urn \ | jq -r '[.. | .networkInterfaceAttachments? // empty | .[].networkInterfaceUrn] | first')" origin network list-floating-ips --project-urn \ | jq -r --arg nic "$nic" '.. | objects | select(.networkInterfaceUrn? == $nic) | .address' ``` 1. Verify that you can log in, as the instance’s `loginUser`, with the private key of the key pair: ```sh ssh -i @ ``` The VPC’s default security group allows SSH from anywhere. If you attached other security groups, one of them must allow inbound TCP port 22 from your address. ## Using the API [#using-the-api] The `launchInstance` mutation takes the same inputs. It also accepts `imageFamily` in place of `imageUrn`, which launches the image currently designated for that family. Set exactly one of the two. See [Image families](/docs/compute/images/image-families). ```graphql mutation { compute { launchInstance(input: { projectUrn: "" imageFamily: "" instanceType: "gp1.core.2" keyPairUrn: "" bootVolume: { sizeInGib: 40 } }) { urn status loginUser } } } ``` ## If the launch is refused [#if-the-launch-is-refused] A refused launch creates nothing and costs nothing. - The message names the type and what was short. See [`INSUFFICIENT_CAPACITY`](/docs/platform/reference/errors#insufficient_capacity). - `PRODUCT_UNAVAILABLE`: the instance type or storage class isn’t offered. Pick one whose `available` is `true`. See [`PRODUCT_UNAVAILABLE`](/docs/platform/reference/errors#product_unavailable). - Quota: the launch would take the organization or project past an instance, vCPU or storage limit. The error names the quota. See [Limits](/docs/platform/reference/limits). - Root disk too small: `--boot-volume-size-gib` is smaller than the image. The error names the smallest size that works. For other problems, see [Troubleshoot Compute](/docs/compute/troubleshooting). ## Next steps [#next-steps] - [Attach a volume](/docs/compute/instance-storage/attach-detach) - [Associate a floating IP](/docs/network/internet-access/floating-ips#use-a-floating-ip), for an instance in a subnet that doesn’t assign public addresses automatically - [Stop and start an instance](/docs/compute/instances/stop-start) ## Related [#related] - [`launch-instance` reference](/docs/compute/reference/cli#launch-instance) - [Instance lifecycle](/docs/compute/instances/lifecycle) # Instance lifecycle The eight statuses an instance moves through from launch to termination, what changes each one, what you're billed for, and what FAILED means. An instance’s status is always one of eight values. Four of them are transitional and resolve on their own. `RUNNING`, `STOPPED` and `FAILED` change only when something asks for a change, and `TERMINATED` is final. Every lifecycle operation is asynchronous: the call returns once the platform accepts the request, and `status` tells you what happened. The following diagram shows every transition you can observe. You can also terminate an instance that is `INITIALIZING`, `PENDING` or `STOPPING`. The diagram leaves those edges out to stay readable. ## Statuses [#statuses] `status` is a typed enum in the API. A client generated from the schema gets the full set, so compare against the enum rather than against strings you’ve seen in a response. | `status` | What it means | Compute billed | | --- | --- | --- | | | Just launched. Its root disk and network interface are being created. Not running, not reachable. Moves on by itself. | No | | | Everything it needs is ready and the platform has asked its host to start it. Moves on by itself. | No | | | The host confirmed the instance started. | Yes | | | A stop was requested. The guest may still be running until it shuts down. Moves on by itself. | No | | | Not running, but still yours. Its network interface stays reserved and its volumes stay attached. You can start it again. | No | | | A termination was requested. The guest is being shut down if it was running, and the instance’s resources are being released. Moves on by itself. | No | | | Permanently gone, and the resources it held are released. Nothing leaves this status. | No | | | The host didn’t do what it was asked, or something the instance needs could not be created. Always carries a `statusReason`. | No | Compute usage stops being metered as soon as the instance leaves `RUNNING`. Volumes are billed separately for as long as they exist, so a `STOPPED` instance’s root disk is still billed. For storage billing, see [Volumes](/docs/storage/volumes). ## Changes nobody asked the platform for [#changes-nobody-asked-the-platform-for] Two transitions happen without a stop request: - Guest power-off. When you shut the operating system down from inside the guest (`poweroff`, `shutdown -h`), the instance goes from `RUNNING` straight to `STOPPED`, without `STOPPING`. Its `statusReason` stays `null`. Start it again the usual way. - Machine failure. When the platform can prove the machine under a running instance failed, it records the instance as `STOPPED` with a `statusReason` that says so. For details, see [When the machine under an instance fails](/docs/compute/instances/host-failure). ## Polling [#polling] Poll through the transitional statuses: `INITIALIZING`, `PENDING`, `STOPPING` and `SHUTTING_DOWN`. Stop polling when the instance reaches `RUNNING`, `STOPPED`, `FAILED` or `TERMINATED`. `RUNNING` means the host confirmed the start. It doesn’t prove the guest’s operating system and network are up. To know that, read the instance’s health checks. For more information, see [Instance health checks](/docs/compute/instances/health-checks). ## When a lifecycle operation fails [#when-a-lifecycle-operation-fails] If the host can’t carry out a start or a stop, the instance ends up `FAILED`. It never stays in a transitional status waiting for something that isn’t coming. `FAILED` means one thing: the platform can’t confirm the instance is where you asked it to be. It doesn’t promise that the guest is stopped or gone. The common cases: - A launch or start that failed. The host refused the start, or a volume or network interface the instance needs could not be created or attached. `statusReason` says which. - A stop that failed. The guest may still be running. - An operation the host never confirmed. If the instance’s host is reachable but doesn’t confirm a start or a stop, the platform sends the request again, three times in total, about 10 minutes apart. An instance can therefore sit in `PENDING`, `STOPPING` or `SHUTTING_DOWN` for about 30 minutes before it becomes `FAILED`, with a `statusReason` saying the host did not confirm. A `FAILED` instance keeps its network interface and volumes, stays listed, and never retries on its own. You have two ways forward: - Start it. `start-instance` moves it to `PENDING` and back into the normal lifecycle. There is no separate “retry the stop”: start it, then stop it again. - Terminate it. Terminating a `FAILED` instance doesn’t wait for its host to confirm the guest is gone, because the host may not answer at all. The platform releases the instance’s resources, stops billing and reports `TERMINATED`. A `FAILED` instance can still hold capacity on its host, and you can’t change its type. Don’t leave one sitting indefinitely. Every possible `statusReason` is listed in [Status reasons](/docs/compute/reference/status-reasons). ## Terminated instances [#terminated-instances] A terminated instance stays in `list-instances` for 2 hours after it terminates, then drops out of the default list. You can still read it by its URN with `get-instance`, however long ago it terminated. ## Related [#related] - [Stop and start an instance](/docs/compute/instances/stop-start) - [Terminate an instance](/docs/compute/instances/terminate) - [Status reasons](/docs/compute/reference/status-reasons) - [Troubleshoot Compute](/docs/compute/troubleshooting) # Stop and start an instance Stop an instance to release its vCPU and memory while keeping its disks and addresses, and start it again later, possibly on another machine. Stop an instance when you don’t need it running. A stopped instance accrues no compute usage, and it keeps its volumes, network interface and addresses. Start it again when you need it, the same instance, possibly on a different machine. ## Before you begin [#before-you-begin] - To stop: an instance in `RUNNING`. - To start: an instance in `STOPPED` or `FAILED`. - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). A stopped instance’s volumes are still billed. Terminating the instance stops billing for it and deletes the volumes its launch created, except a volume that has a snapshot: that one stays and is still billed. See [Terminate an instance](/docs/compute/instances/terminate). ## Stop the instance [#stop-the-instance] 1. Request the stop: ```sh origin compute stop-instance --instance-urn ``` The platform asks the guest operating system to shut down cleanly. A guest that hasn’t shut down after 5 minutes is powered off. 1. Run `get-instance` until `status` reads `STOPPED`: ```sh origin compute get-instance --instance-urn ``` The instance passes through `STOPPING` first. You can also shut the guest down from inside, with `sudo poweroff`. The instance then goes from `RUNNING` straight to `STOPPED`. ## Start the instance [#start-the-instance] 1. Request the start: ```sh origin compute start-instance --instance-urn ``` 1. Run `get-instance` until `status` reads `RUNNING`. The instance passes through `PENDING` first. 1. Verify that the guest is up. Its `healthChecks.availability` reads `AVAILABLE` once the platform has seen its network stack answer. See [Instance health checks](/docs/compute/instances/health-checks). Starting an instance that is already `RUNNING` reports success and changes nothing. Starting one that is still `PENDING` re-sends the start it is waiting for, without disturbing a guest that is coming up. A start is refused while the instance is `INITIALIZING`, because it starts on its own once its resources are ready, and while it is `STOPPING` or `SHUTTING_DOWN`. ## Using the API [#using-the-api] The `startInstance` and `stopInstance` mutations take the instance URN: ```graphql mutation { compute { stopInstance(input: { instanceUrn: "" }) { accepted message } } } ``` ## If this fails [#if-this-fails] - The start is refused with `PRODUCT_UNAVAILABLE`. The instance’s type is no longer offered. Change it to an available type, then start it. See [Change an instance’s type](/docs/compute/instances/change-type). - The start is refused with `INSUFFICIENT_CAPACITY`. A stopped instance is placed afresh when it starts. To try a larger type, change the instance’s type first. See [Change an instance’s type](/docs/compute/instances/change-type). - The instance ends up `FAILED`. Read its `statusReason`. See [When a lifecycle operation fails](/docs/compute/instances/lifecycle#when-a-lifecycle-operation-fails). ## Related [#related] - [`stop-instance` reference](/docs/compute/reference/cli#stop-instance) - [`start-instance` reference](/docs/compute/reference/cli#start-instance) - [Instance lifecycle](/docs/compute/instances/lifecycle) # Terminate an instance Terminate an instance permanently, and learn which of its volumes, network interfaces and addresses are deleted and which stay with you. Terminate an instance when you no longer need it. Termination is permanent and stops billing for the instance. The volumes its launch created are deleted with it, unless a volume has a snapshot: then it stays, and it’s still billed. See [What happens to the instance’s resources](#what-happens-to-the-instances-resources). ## Before you begin [#before-you-begin] - Copy off any data you need from the instance’s root disk. The root disk and every other volume the launch created are deleted with the instance, and there is no option to keep them. - Detach any volume you want to keep using elsewhere, or let termination release it. Volumes you attached yourself are never deleted. See [Attach and detach volumes](/docs/compute/instance-storage/attach-detach). Termination can’t be undone. The instance, its root disk and its launch-created network interface are gone for good. ## Terminate the instance [#terminate-the-instance] 1. Request the termination: ```sh origin compute terminate-instance --instance-urn ``` You can terminate an instance in any status. A `FAILED` instance is terminated without waiting for its machine to confirm the guest is gone. 1. Run `get-instance` until `status` reads `TERMINATED`: ```sh origin compute get-instance --instance-urn ``` The instance passes through `SHUTTING_DOWN` while its resources are released, normally for a few seconds. Terminating is safe to repeat. If you aren’t sure an earlier attempt went through, call it again. Terminating an instance that is already `TERMINATED` reports success and changes nothing. ## What happens to the instance’s resources [#what-happens-to-the-instances-resources] | Resource | On termination | | --- | --- | | Root disk and other launch-created volumes | Deleted. | | Volumes you attached yourself | Detached and `AVAILABLE` again. Not deleted. | | Launch-created network interface | Deleted, with any public address the platform assigned to it automatically. | | Floating IP you allocated yourself | Disassociated. It stays allocated to you until you release it. See [Floating IPs](/docs/network/internet-access/floating-ips). | A launch-created volume that has a snapshot can’t be deleted, so it stays `AVAILABLE` and billed after the instance terminates. Its `retentionNote` says why. Delete the snapshots, then the volume. See [Delete a volume](/docs/storage/volumes/delete). If something else can’t be released, the instance still reaches `TERMINATED` and stops costing you anything. The attachment for that resource keeps naming it and says it could not be released. A terminated instance stays in `list-instances` for 2 hours, then drops out of the default list. You can still read it with `get-instance` at any time. ## Using the API [#using-the-api] ```graphql mutation { compute { terminateInstance(input: { instanceUrn: "" }) { accepted message } } } ``` ## Related [#related] - [`terminate-instance` reference](/docs/compute/reference/cli#terminate-instance) - [Instance lifecycle](/docs/compute/instances/lifecycle) # Create a key pair Import the public half of an SSH key you already have, or have the platform generate a key pair and save its private key from the one response that carries it. Create a key pair before you launch an instance. Import a key you already have, or have the platform generate one. Importing is the safer default, because the private key never leaves your computer. ## Before you begin [#before-you-begin] - A project to create the key pair in. Key pairs belong to one project. - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). ## Import an existing key [#import-an-existing-key] 1. If you don’t have a key yet, create one locally: ```sh ssh-keygen -t ed25519 -f ~/.ssh/origin-cloud ``` 1. Import its public half. Pass the full OpenSSH public key line: ```sh origin compute import-key-pair \ --project-urn \ --name my-key \ --public-key "$(cat ~/.ssh/origin-cloud.pub)" ``` A key with an unsupported type, or more than one line, is refused. 1. Verify that the key pair is listed: ```sh origin compute list-key-pairs --project-urn ``` ## Generate a key pair [#generate-a-key-pair] 1. Generate the key pair: ```sh origin compute generate-key-pair \ --project-urn \ --name my-key ``` The response contains `privateKey`, an `ssh-ed25519` private key in OpenSSH format. 1. Save `privateKey` to a file right away, and restrict its permissions. To do both in one go, generate the key pair and write `privateKey` straight to a file with `jq`, instead of running the command above on its own: ```sh origin compute generate-key-pair \ --project-urn \ --name my-key \ | jq -r '.. | .privateKey? // empty' > ~/.ssh/origin-cloud chmod 600 ~/.ssh/origin-cloud ``` The private key is returned only in this response. The platform doesn’t store it and can’t show it again. If you lose it, delete the key pair and create a new one. 1. Verify that the key pair is listed: ```sh origin compute list-key-pairs --project-urn ``` ## Using the API [#using-the-api] The `importKeyPair` and `generateKeyPair` mutations take the same inputs. Request `privateKey` in the `generateKeyPair` selection, or you can’t get it later: ```graphql mutation { compute { generateKeyPair(input: { projectUrn: "", name: "my-key" }) { urn publicKey privateKey } } } ``` ## Next steps [#next-steps] - [Launch an instance](/docs/compute/instances/launch) with the key pair ## Related [#related] - [`import-key-pair` reference](/docs/compute/reference/cli#import-key-pair) - [`generate-key-pair` reference](/docs/compute/reference/cli#generate-key-pair) - [Key pairs](/docs/compute/key-pairs) # Key pairs A key pair is the SSH key you log in to instances with. Learn how the platform uses it at launch and what happens when you delete one. A key pair is an SSH key registered in a project. Every launch names one, and the platform installs its public half for the instance’s login user. You log in with the matching private key. There is no password login and no shared fallback key: a launch without a key pair is refused. The following table shows how a key pair gets into an instance. | From | Step | To | | --- | --- | --- | | Imported public key or generated key pair | becomes | Key pair | | Key pair | named at launch | Instance login user | | You with the private key | SSH | Instance login user | ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Imported key pair | You upload the public half of a key you already have. The private key never leaves your machine. Accepted key types are `ssh-ed25519`, `ssh-rsa`, `ssh-dss` and `ecdsa-sha2-nistp256`, `-nistp384` and `-nistp521`. | | Generated key pair | The platform generates an `ssh-ed25519` key pair and returns the private key in the response, once. The platform stores only the public half, so the private key can never be retrieved again. | | Login user | The account the public key is installed for. See [Guest environment](/docs/compute/instances/guest-environment). | ## What you can do [#what-you-can-do] - [Create a key pair](/docs/compute/key-pairs/create), by importing or generating it - List key pairs with `origin compute list-key-pairs` and read one with `origin compute get-key-pair` - Delete a key pair with `origin compute delete-key-pair` Deleting a key pair doesn’t change instances already launched with it. Their login user keeps the public key, and the matching private key still logs in. You can no longer launch new instances with it. ## Related [#related] - [Launch an instance](/docs/compute/instances/launch) - [origin compute commands](/docs/compute/reference/cli) # origin compute commands Every origin compute command with its flags: instances, instance types, images, image families, key pairs and volume attachments. This page lists every `origin compute` command. For the options every `origin` command accepts, see [Global options](/docs/platform/reference/cli#global-options). ## launch-instance [#launch-instance] Launch a new instance. ```sh origin compute launch-instance [OPTIONS] --project-urn --image-urn --key-pair-urn --instance-type ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--image-urn ` | yes | Image to use. | | `--subnet-urn ` | no | Subnet the Instance will belong to. Omit to use the project’s default subnet - lazily created, on first use, in a VPC with an Internet Gateway already attached and a public IP auto-assigned to the instance’s interface. | | `--key-pair-urn ` | yes | SSH key pair to inject into the guest’s default user. | | `--instance-type ` | yes | Instance type to launch, e.g. “`gp1.core.2`” - see [`list-instance-types`](#list-instance-types) for the full live catalog. | | `--volume-backend ` | no | Storage backend for the instance’s volumes. Only `pvs`, the default, is accepted; omit this option. | | `--boot-volume-size-gib ` | no | Size of the instance’s root disk, in GiB. Omitted takes the image’s own size, which is also the smallest value accepted - a smaller one is refused rather than raised. | | `--boot-volume-storage-class ` | no | Performance tier for the instance’s root disk, e.g. “`gp1`” - see [`origin storage list-storage-classes`](/docs/storage/reference/cli#list-storage-classes) for the tiers currently on offer. Omitted takes the default. | | `--security-group-urn ` | no | Security groups to attach to the primary network interface. Repeatable. Omitted defaults to the VPC’s default security group. | | `--login-user ` | no | The account to create on the guest and inject the key pair into, overriding the image’s default user for this instance. A POSIX username other than `root`. Omitted takes the image’s default; either way the instance reports the result as `loginUser` | ## list-instance-types [#list-instance-types] List the live catalog of launchable instance types. ```sh origin compute list-instance-types ``` This command takes no options. ## list-image-families [#list-image-families] List every image family on offer. A family is a stable name that resolves to the image currently designated for it. `supportEndsAt`, when set, is when upstream support for that release ends; it is advisory and nothing is refused on it. The CLI launches by image URN only; to launch by family, use the `imageFamily` field of the `launchInstance` GraphQL mutation. ```sh origin compute list-image-families ``` This command takes no options. ## import-key-pair [#import-key-pair] Import the public half of an SSH key pair you already have, for use when launching instances. ```sh origin compute import-key-pair --project-urn --name --public-key ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--name ` | yes | Name for the key pair. | | `--public-key ` | yes | Full OpenSSH public key line, e.g. `ssh-ed25519 AAAA... comment` | ## generate-key-pair [#generate-key-pair] Generate an SSH key pair on the platform. The private key is in the response and is never retrievable again - save it immediately. ```sh origin compute generate-key-pair --project-urn --name ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--name ` | yes | Name for the key pair. | ## list-key-pairs [#list-key-pairs] List the key pairs of a project. ```sh origin compute list-key-pairs --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-key-pair [#get-key-pair] Get a single key pair. ```sh origin compute get-key-pair --key-pair-urn ``` | Option | Required | Description | | --- | --- | --- | | `--key-pair-urn ` | yes | URN of the key pair. | ## delete-key-pair [#delete-key-pair] Delete a key pair. ```sh origin compute delete-key-pair --key-pair-urn ``` | Option | Required | Description | | --- | --- | --- | | `--key-pair-urn ` | yes | URN of the key pair. | ## list-instances [#list-instances] List the instances of a project. ```sh origin compute list-instances --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-instance [#get-instance] Get one instance, including its volume attachments. ```sh origin compute get-instance --instance-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | ## list-volume-attachments [#list-volume-attachments] List the attachments that reference a Volume, each naming its Instance. Use it to find which Instance holds a volume that is `INUSE`: the entry whose `id` equals the volume’s `claimRef` (see [`origin storage get-volume`](/docs/storage/reference/cli#get-volume)) is the one holding it, and its `instanceUrn` is the Instance. Normally there is exactly one entry, with status `ATTACHED`; detached attachments are not listed. A volume from another project returns an empty list. ```sh origin compute list-volume-attachments --project-urn --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project the volume belongs to. | | `--volume-urn ` | yes | URN of the Volume. | ## start-instance [#start-instance] Start a stopped Instance. ```sh origin compute start-instance --instance-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | ## stop-instance [#stop-instance] Stop a running instance. Its network interface and volumes stay with it. ```sh origin compute stop-instance --instance-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | ## change-instance-type [#change-instance-type] Change a stopped Instance’s type, so it starts again at a different size. The Instance must be stopped. It keeps its identity, its address and its volumes; only the size changes. Growing is checked against the same vCPU quota a launch is. [`list-instance-types`](#list-instance-types) shows what you can change to. ```sh origin compute change-instance-type --instance-urn --instance-type ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | | `--instance-type ` | yes | The type to change to, e.g. “`gp1.core.4`”. | ## terminate-instance [#terminate-instance] Terminate an instance. Its network interface and the volumes its launch created are deleted; volumes you attached yourself are detached and kept. ```sh origin compute terminate-instance --instance-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | ## attach-volume [#attach-volume] Attach an available volume to an instance, running or stopped. On a running instance the disk is hot-plugged: the attachment reports `ATTACHING` and settles to `ATTACHED` once the guest sees the device. On a stopped instance it appears at the next start. ```sh origin compute attach-volume [OPTIONS] --instance-urn --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | | `--volume-urn ` | yes | URN of the Volume. | | `--device-name ` | no | Guest device name (`vda`..`vdz`). Assigned by the platform when omitted. | ## detach-volume [#detach-volume] Detach a volume from an instance, running or stopped, making it available again. On a running instance the attachment reports `DETACHING` until the guest releases the device; the volume becomes available only after that. ```sh origin compute detach-volume --instance-urn --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--instance-urn ` | yes | URN of the Instance. | | `--volume-urn ` | yes | URN of the Volume. | ## create-image [#create-image] Create an image from a protected snapshot. ```sh origin compute create-image [OPTIONS] --project-urn --root-device-snapshot-urn --description ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--root-device-name ` | no | Root device name: a bare virtio target, `vda`.. `vdz` (`vdc` is reserved) - not a `/dev/` path [default: `vda`]. | | `--root-device-size ` | no | Root device size in GiB [default: 8]. | | `--root-device-snapshot-urn ` | yes | Root device backing Snapshot. | | `--default-user ` | no | The account instances launched from this image log in as - the non-root user created at first boot, holding the launch’s SSH key. A POSIX username other than `root`; defaults to `cloud` | | `--description ` | yes | Description of the Image. | ## list-images [#list-images] List the images available to a project, your own and platform-provided. ```sh origin compute list-images --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-image [#get-image] Get one image. ```sh origin compute get-image --image-urn ``` | Option | Required | Description | | --- | --- | --- | | `--image-urn ` | yes | URN of the Image. | ## update-image [#update-image] Update a customer-owned Image’s description - the only mutable field. ```sh origin compute update-image --image-urn --description ``` | Option | Required | Description | | --- | --- | --- | | `--image-urn ` | yes | URN of the Image. | | `--description ` | yes | New description. | ## delete-image [#delete-image] Delete a customer-owned Image. ```sh origin compute delete-image --image-urn ``` | Option | Required | Description | | --- | --- | --- | | `--image-urn ` | yes | URN of the Image. | # Compute reference Complete reference material for Compute - every origin compute command and its options, and every reason an instance can report in statusReason. These pages list everything of one kind. For explanations, follow the links back to the concept pages. ## Pages [#pages] - [origin compute commands](/docs/compute/reference/cli): every `origin compute` command with its options. - [Status reasons](/docs/compute/reference/status-reasons): every text an instance can report in `statusReason`, what it means and what to do. ## Shared reference [#shared-reference] - [Error codes](/docs/platform/reference/errors) – the error codes every API call can return - [Limits](/docs/platform/reference/limits) – Compute quotas - [Global CLI options](/docs/platform/reference/cli#global-options) # Status reasons Every text an instance can report in statusReason when it is FAILED or was stopped by the platform, with what each means and what to do next. An instance’s `statusReason` says why it is in its current status. `get-instance` and `list-instances` return it next to `status`. It’s set in two cases: - Every `FAILED` instance carries one. - A `STOPPED` instance carries one when the platform stopped it because its machine failed. A `STOPPED` instance you stopped yourself, or that shut itself down, carries none. For every other status it’s `null`, and starting the instance clears it. A reason starts with one of the fixed texts below. Some texts are followed by a colon and a detail, such as a quota refusal you can act on. A reason never contains raw host errors, file paths or machine names. If the reason isn’t enough to act on, contact Origin Cloud support and quote the instance URN. The texts are listed in the order an instance can meet them: launch, start, stop, and machine failure. ## A volume could not be created [#a-volume-could-not-be-created] **Text:** `a volume this instance needs could not be created`, optionally followed by `: ` **Status:** `FAILED` **Meaning:** A volume the launch creates, such as the root disk, could not be created. A detail you can act on is appended, for example `a volume this instance needs could not be created: invalid input on field quota: volume storage quota exceeded`. **What to do:** For a quota detail, free volume storage or request a higher limit. Then terminate the instance and launch again. ## A volume could not be attached [#a-volume-could-not-be-attached] **Text:** `a volume this instance needs could not be attached`, optionally followed by `: ` **Status:** `FAILED` **Meaning:** A volume exists but couldn’t be handed to the instance, for example `a volume this instance needs could not be attached: volume is not available`. **What to do:** Act on the detail, then start the instance or terminate it. ## The network interface could not be created [#the-network-interface-could-not-be-created] **Text:** `the network interface this instance needs could not be created`, optionally followed by `: ` **Status:** `FAILED` **Meaning:** The launch couldn’t create the instance’s network interface. The most common detail is a subnet with no free addresses. The launch call returns the same error. **What to do:** Terminate the instance. Launch again into a subnet with free addresses. See [VPC addressing](/docs/network/vpcs/addressing). ## The instance could not be placed [#the-instance-could-not-be-placed] **Text:** `this instance could not be placed on a machine to start on`, optionally followed by `: ` **Status:** `FAILED` **Meaning:** The instance finished preparing its resources but had no machine to start on, and none could be found. The detail usually names the capacity shortfall, for example `no host has capacity for an instance of this type`. **What to do:** Start the instance again later, or terminate it and launch again. ## The instance could not be started on its host [#the-instance-could-not-be-started-on-its-host] **Text:** `the instance could not be started on its host` **Status:** `FAILED` **Meaning:** The machine the instance was placed on refused to start it. **What to do:** Start the instance again, or terminate it. ## The start operation failed [#the-start-operation-failed] **Text:** `the operation failed (ERR_INSTANCE_START)` **Status:** `FAILED` **Meaning:** The host reported an error while carrying out the start. **What to do:** Start the instance again, or terminate it. ## The stop operation failed [#the-stop-operation-failed] **Text:** `the operation failed (ERR_INSTANCE_STOP)` **Status:** `FAILED` **Meaning:** The host reported an error while carrying out a stop or a termination’s shutdown. The guest may still be running. **What to do:** Start the instance to return it to the normal lifecycle and stop it again, or terminate it. ## The operation failed [#the-operation-failed] **Text:** `the operation failed` **Status:** `FAILED` **Meaning:** The host reported an error without a classification. **What to do:** Start the instance again, or terminate it. ## The host did not confirm the start [#the-host-did-not-confirm-the-start] **Text:** `the instance's host did not confirm that it started` **Status:** `FAILED` **Meaning:** The instance’s machine is reachable but didn’t confirm a start, after the platform sent it three times over about 30 minutes. The guest may be running. **What to do:** Start the instance again, or terminate it. ## The host did not confirm the stop [#the-host-did-not-confirm-the-stop] **Text:** `the instance's host did not confirm that it stopped` **Status:** `FAILED` **Meaning:** The instance’s machine is reachable but didn’t confirm a stop or a termination’s shutdown, after the platform sent it three times over about 30 minutes. The guest may still be running. **What to do:** Start the instance to return it to the normal lifecycle and stop it again, or terminate it. ## The machine failed [#the-machine-failed] **Text:** `the machine this instance was running on failed, and the instance went down with it; start it again to bring it back` **Status:** `STOPPED` **Meaning:** The machine under the running instance restarted, and the platform proved it. The guest didn’t survive. See [When the machine under an instance fails](/docs/compute/instances/host-failure). **What to do:** Start the instance when you want it back. A start usually brings it back; check that the guest answers afterwards. If it reads `RUNNING` and `AVAILABLE` but stays unreachable, see [Troubleshoot Compute](/docs/compute/troubleshooting#running-and-available-after-a-machine-failure-but-unreachable). ## The machine was taken out of service [#the-machine-was-taken-out-of-service] **Text:** `the machine this instance was running on failed and has been taken out of service; the instance went down with it, and starting it again will place it on another machine` **Status:** `STOPPED` **Meaning:** The machine under the instance failed and didn’t come back, and the platform took it out of service. See [When the machine under an instance fails](/docs/compute/instances/host-failure). **What to do:** Start the instance when you want it back. It starts on another machine with its volumes and addresses unchanged. # Troubleshoot Compute Fix common Compute problems - failed instances, refused launches and starts, impaired or unknown health, unsynchronized clocks, SSH failures and broken pod networking. Each section starts from what you see. For the meaning of every `statusReason`, see [Status reasons](/docs/compute/reference/status-reasons). ## Find your symptom [#find-your-symptom] Entries marked describe what we ran into while testing on 12 October 2026. They are not on docs.origincloud.eu yet. ## Instance status is FAILED [#instance-status-is-failed] `get-instance` shows `status: FAILED` and a `statusReason`. The host refused or never confirmed a start or a stop, or a volume, network interface or placement the instance needed failed. `FAILED` doesn’t mean the guest is stopped. - Read `statusReason` and look it up in [Status reasons](/docs/compute/reference/status-reasons). - Fix anything the reason names, such as a quota or a full subnet. - Start the instance with `origin compute start-instance`, or terminate it with `origin compute terminate-instance`. Don’t leave a `FAILED` instance sitting, because it can still hold capacity. ## Launch refused with INSUFFICIENT_CAPACITY [#launch-refused-with-insufficient_capacity] The launch or start fails with `INSUFFICIENT_CAPACITY` and a message such as `insufficient capacity for instance type gp1.core.16: no host has 16 vCPU and 65536 MiB memory free right now; retry later, …`. No machine has room for that instance type right now, or no machine serves its kind. This is a refusal, not a fault. Nothing was created. - Retry the same request in a few minutes. - Or choose a larger type whose `available` is `true`, or a type of another kind. See [Instance types](/docs/compute/instances/instance-types). The API message goes on to suggest a smaller type. For `gp1.core.2` there is none. ## Start or change-type refused with PRODUCT_UNAVAILABLE [#start-or-change-type-refused-with-product_unavailable] `start-instance`, `change-instance-type` or `launch-instance` fails with `PRODUCT_UNAVAILABLE`, naming an instance type or storage class. The type or class is no longer offered, or isn’t on sale. A stopped instance whose type was withdrawn can’t start as that type. 1. List the types and pick one whose `available` is `true`: ```sh origin compute list-instance-types ``` 1. For a stopped instance, change its type, then start it. See [Change an instance’s type](/docs/compute/instances/change-type). ## GUEST_PRESENT is IMPAIRED [#guest_present-is-impaired] The instance is `RUNNING`, but `healthChecks` shows `GUEST_PRESENT` as `IMPAIRED` and `availability` as `IMPAIRED`. The machine carrying the instance is reachable and no longer runs it. Waiting won’t bring it back. - Stop the instance and wait for `STOPPED`. - Start it again. It can start on any machine, with its volumes and addresses unchanged. See [Instance health checks](/docs/compute/instances/health-checks). ## Health checks show INSUFFICIENT_DATA [#health-checks-show-insufficient_data] Checks read `INSUFFICIENT_DATA` and `availability` reads `UNKNOWN`, often with `HOST_REACHABLE` as `IMPAIRED` first. The platform has lost contact with the machine carrying the instance, so it can’t observe the instance. It doesn’t know whether the instance is still running. Right after launch, checks also read `INSUFFICIENT_DATA` until the first observation arrives. - Wait a few minutes. If the machine comes back, the checks return to OK. - If the machine failed, the platform records the instance as `STOPPED` with a `statusReason`. Start it again. See [When the machine under an instance fails](/docs/compute/instances/host-failure). - If `HOST_REACHABLE` stays `IMPAIRED`, or the checks stay `INSUFFICIENT_DATA` on a running instance, contact Origin Cloud support. The `SYSTEM` category means there is nothing to fix inside the instance. ## System clock synchronized: no [#system-clock-synchronized-no] `timedatectl` inside the instance shows `System clock synchronized: no`. Either the guest isn’t using the platform’s time service, or the physical machine’s own clock isn’t synchronized and the platform is telling the guest not to trust it. - Check that `NTP service: active` is shown. If it isn’t, enable the guest’s time service with `sudo timedatectl set-ntp true`. - If you pointed the guest at an external time server, check that the instance has internet access. - If the guest uses the platform’s time service and the clock stays unsynchronized, contact Origin Cloud support. See [Guest environment](/docs/compute/instances/guest-environment). ## Can’t connect over SSH [#cant-connect-over-ssh] `ssh` times out, or fails with `Permission denied (publickey)`. The wrong user name or key, a security group that doesn’t allow port 22, or an instance with no public address. - Check the user name. Use the instance’s `loginUser` from `get-instance`, not `root`. - Check the key. Use the private key of the key pair the instance was launched with. - Check that a security group on the instance’s network interface allows inbound TCP port 22 from your address. The VPC’s default group does, unless its rules were changed. See [Security groups](/docs/network/traffic-control/security-groups). - Check that the instance has a public address, either assigned at launch in the default subnet or a floating IP you associated. See [Floating IPs](/docs/network/internet-access/floating-ips). - Check that the instance is `RUNNING` and its `availability` is `AVAILABLE`. - If every check passes and you still can’t connect, stop the instance, wait for `STOPPED`, and start it again. If that doesn’t help, contact Origin Cloud support with the instance URN and the time you last connected. The API and the CLI have no reboot operation and no console log to read. ## Running and available after a machine failure, but unreachable [#running-and-available-after-a-machine-failure-but-unreachable] The instance was `STOPPED` with a machine-failure `statusReason`. You started it, and it now reads `RUNNING` with `availability` `AVAILABLE`, but SSH and every other port time out. The guest didn’t come back up after the start, although the instance’s status and health checks don’t show it. Moving the instance’s Floating IP off and back doesn’t help. Query the instance’s CPU use for the last 15 minutes with the `RATE` of `oc_compute_instance_cpu_seconds_total`. See [Query metrics](/docs/observability/query-metrics). A guest that is up uses some CPU; values of `0` throughout mean it isn’t running anything. 1. Stop the instance and wait for `STOPPED`. 1. Start it again and wait for `RUNNING`. Then connect over SSH, or check the CPU metric again. 1. If it’s still unreachable, contact Origin Cloud support. Quote the instance URN, the time of the machine failure, and the time of each start. ## Pod networking broken between cloned instances [#pod-networking-broken-between-cloned-instances] Instances launched from your own image can’t reach each other over VXLAN. Kubernetes pod networking with VXLAN or Geneve encapsulation fails between nodes, while the nodes reach each other directly. The instances share one machine-id, inherited from the image. Their VXLAN devices then get the same MAC address and can’t exchange packets. 1. Run `cat /etc/machine-id` on two affected instances. Identical output confirms the cause. 1. On each affected instance, generate a new machine-id and reboot: ```sh sudo rm -f /etc/machine-id /var/lib/dbus/machine-id sudo systemd-machine-id-setup sudo reboot ``` 1. Fix the image so new instances don’t inherit it. Clear the machine-id before you snapshot. See [Create an image](/docs/compute/images/create). ## Related [#related] - [Status reasons](/docs/compute/reference/status-reasons) - [Error codes](/docs/platform/reference/errors) - [Troubleshoot storage](/docs/storage/troubleshooting) - [Troubleshoot networking](/docs/network/troubleshooting) # Access model How principals, roles, role assignments and permissions work together, how org-wide and project scopes differ, and how a request is authorized. Access in Origin Cloud is granted by role assignments. A role assignment gives one principal one built-in role, either across the whole organization or for a single project. Every request is allowed only if one of the caller’s assignments covers the resource and carries the permission the request needs. ## Principals [#principals] A principal is whoever or whatever is granted access. You refer to a principal by a typed identifier, in the same form whether you assign a role, revoke one, or check a permission. | Principal | Format | Where to find the ID | | --- | --- | --- | | User | `user:` | `userId` in `origin iam current-user`, or the `principal` column of `list-members` | | Service account | `service_account:` | The `principal` field returned when you create a service account or list them | Both IDs are UUIDs. A user ID belongs to the person’s account and is the same in every organization they’re a member of. ## Roles [#roles] A role is a named, fixed set of permissions. Every role is built in: you can assign and revoke them, but you can’t create, change or delete a role. Each role has a short ID such as `roles/owner` and a URN, which is what you pass to role commands, for example `urn:origin:cloud:iam::::tc/role/roles/owner`. The `list-roles` command shows every role with its URN and permissions. For the full catalog, see [Built-in roles](/docs/iam/roles). ## Permissions [#permissions] A permission allows one action on one kind of resource. Its key has three dotted parts: the service, the resource type and the action, for example `network.vpc.list` or `iam.member.create`. Each API operation requires exactly one permission. When a request is refused, the error names the permission it needed: ```text Insufficient permissions. This operation requires permission `iam.member.create` on `org/` ``` The `permissions` command lists every permission the platform defines. ## Role assignments and scopes [#role-assignments-and-scopes] A role assignment links a principal, a role and a scope. The scope is either the whole organization or one project in it. | Scope | Where the role applies | | --- | --- | | Org-wide | The role applies to the organization itself and to every resource in every project of the organization, including projects created later. | | Project scope | The role applies only to resources inside that one project. It doesn’t apply to the organization itself. | All IAM operations, such as inviting members, assigning roles and creating service accounts, act on the organization. A project-scoped assignment therefore never allows them, even for `roles/owner`. To let someone manage access, assign the role org-wide. The billing roles must always be assigned org-wide; see [Billing access](/docs/platform/billing/billing-access). Whoever creates an organization receives `roles/owner` and `roles/billing/administrator` org-wide. Anyone else holds only the roles you assign to them. ## Who can assign a role [#who-can-assign-a-role] Assigning and revoking roles needs `iam.role.assign` or `iam.role.revoke` on the organization. On top of that, you can only assign or revoke a role whose permissions you hold yourself at the scope of the grant. For an org-wide grant, your org-wide assignments count. For a project-scoped grant, your org-wide assignments and your assignments in that project count. Nobody can use role management to gain access they don’t already have. This applies to every path that changes a grant: - [Assigning and revoking a role](/docs/iam/assign-roles). - [Inviting a member](/docs/iam/manage-members#invite-a-member): you can only invite with a role you could assign. A pending invite is checked again when it’s applied. If the person who sent it can no longer assign the role by then, the invite is dropped. - [Removing a member](/docs/iam/manage-members#remove-a-member): you must be able to revoke every role the member holds. A request that would go beyond your own permissions is refused with `FORBIDDEN`. The error names the role and some of the permissions you lack. For example, Owner holds no billing permission, so an Owner can assign a billing role only if it also holds `roles/billing/administrator`. An IAM Editor can’t assign Owner. ## How a request is authorized [#how-a-request-is-authorized] The following steps show how the platform decides whether to allow a request. 1. The request needs a permission on a resource. 1. The platform finds the principal’s role assignments in the resource’s organization. 1. For each assignment: if it’s org-wide or in the resource’s project, and its role contains the permission, the request is allowed. Otherwise the platform skips the assignment and checks the next one. 1. When no assignments are left, the request is refused with `FORBIDDEN`. Permissions only add up. There are no deny rules, so holding a role never takes access away. The check runs on every request, so assigning or revoking a role takes effect on the principal’s next request. A refused request fails with the `FORBIDDEN` error. ## Repeated assignments and revocations [#repeated-assignments-and-revocations] Assigning and revoking are idempotent. Assigning a role that the principal already holds at the same scope, with the same role URN, succeeds and changes nothing. Revoking a role that the principal doesn’t hold at that scope also succeeds and changes nothing. A revocation matches the role URN and the scope exactly. An org-wide grant needs an org-wide revoke, and a project-scoped grant needs the same project. Use the role URN as it appears in the principal’s grants, because a grant created together with the organization carries the organization ID inside its URN. Don’t assemble that URN yourself: list the principal’s grants with `origin iam principal-grants --org-id --principal ` and copy the role URN of the grant you want to revoke. For the steps, see [Assign and revoke roles](/docs/iam/assign-roles). ## The last owner is protected [#the-last-owner-is-protected] An organization always keeps at least one principal with an org-wide `roles/owner` assignment. The platform refuses with `CONFLICT` any revocation or member removal that would take the last org-wide owner away, including your own. A project-scoped owner doesn’t count. To hand over ownership, assign `roles/owner` org-wide to the new owner first, then revoke the old grant. ## Related [#related] - [Built-in roles](/docs/iam/roles) - [Assign and revoke roles](/docs/iam/assign-roles) - [Check access](/docs/iam/check-access) - [Organizations and projects](/docs/platform/organizations) # Assign and revoke roles Grant a built-in role to a user or service account org-wide or for one project, and revoke it again at exactly the scope it was granted. Assign a role to give a user or service account access, and revoke it to take that access away. A change takes effect on the principal’s next request. To give a person access by email instead of by user ID, [invite them](/docs/iam/manage-members#invite-a-member). ## Before you begin [#before-you-begin] - An org-wide `roles/owner` or `roles/iam/editor` assignment, and every permission of the role you assign or revoke at the scope of the grant. For example, an Owner needs `roles/billing/administrator` as well to assign a billing role. See [Who can assign a role](/docs/iam/access-model#who-can-assign-a-role). - Your organization ID (``) and, for a project-scoped grant, the project ID (``). - The principal, in the form `user:` or `service_account:`. `list-members` shows the principal of everyone who already has access. See [Principals](/docs/iam/access-model#principals). ## Assign a role [#assign-a-role] 1. Find the URN of the role you want to assign. ```sh origin iam list-roles --org-id ``` For the permissions of each role, see [Built-in roles](/docs/iam/roles). 1. Assign the role. Omit `--project-id` for an org-wide grant. ```sh origin iam assign-role --org-id \ --principal user: \ --role-urn urn:origin:cloud:iam::::tc/role/roles/viewer ``` To limit the grant to one project, add `--project-id `. A project-scoped grant applies only to resources in that project; it never allows IAM operations. See [Role assignments and scopes](/docs/iam/access-model#role-assignments-and-scopes). 1. Verify the grant. The output lists every principal with its role URNs. ```sh origin iam list-members --org-id ``` Assigning a role the principal already holds at the same scope succeeds and changes nothing. A role URN that isn’t in the built-in catalog is refused with `BAD_REQUEST`. A role with permissions you don’t hold yourself at that scope is refused with `FORBIDDEN`, and so is revoking one. ## Revoke a role [#revoke-a-role] 1. Find the role URN of the grant in the `roleUrns` of the principal in `list-members`. It’s the same URN that `list-roles` shows for the role, for example `urn:origin:cloud:iam::::tc/role/roles/owner`, except for a grant created together with the organization, which carries the organization ID inside its URN. Copy the URN from `list-members` or from `origin iam principal-grants --org-id --principal ` rather than typing it. ```sh origin iam list-members --org-id ``` 1. Revoke the role at the same scope it was assigned with. Omit `--project-id` for an org-wide grant, or pass the same project for a project-scoped one. ```sh origin iam revoke-role --org-id \ --principal user: \ --role-urn urn:origin:cloud:iam::::tc/role/roles/viewer ``` 1. Optionally, run `list-members` again to check that the role URN is gone from the principal. If the principal holds no grant of that role at that scope, the platform refuses with `NOT_FOUND` and changes nothing. Check the scope: an org-wide grant isn’t revoked by a request that names a project, and the reverse. If revoking would leave the organization without an org-wide owner, the platform refuses with `CONFLICT`. Assign `roles/owner` org-wide to someone else first. See [The last owner is protected](/docs/iam/access-model#the-last-owner-is-protected). To take away every role a principal holds in the organization at once, [remove the member](/docs/iam/manage-members#remove-a-member) instead. ## Using the API [#using-the-api] The `assignRole` and `revokeRole` mutations take the same input. Omit `projectId` for an org-wide grant. ```graphql mutation { iam { assignRole(input: { orgId: "" principal: "user:" roleUrn: "urn:origin:cloud:iam::::tc/role/roles/viewer" }) } } ``` ## Related [#related] - [Access model](/docs/iam/access-model) - [Built-in roles](/docs/iam/roles) - [`assign-role`](/docs/iam/reference/cli#assign-role) and [`revoke-role`](/docs/iam/reference/cli#revoke-role) commands - [Audit log](/docs/iam/audit-log) – every assignment and revocation is recorded # Audit log Which access changes the audit log records, the fields of each entry, who can read it, and how to page through it with the GraphQL API. The audit log records changes to access in your organization: who did what, to whom, and when. Entries can’t be changed or deleted through the API. You read the log with the `auditLogEntries` GraphQL query; the CLI has no command for it. ## What’s recorded [#whats-recorded] The audit log records these seven actions. Each one is recorded when the change succeeds. | Action | Recorded when | Target | | --- | --- | --- | | `iam.role.assign` | A role is assigned, including when an invite grants a role to an existing account | The principal | | `iam.role.revoke` | A role is revoked | The principal | | `iam.member.remove` | A member is removed | The principal | | `iam.org_invite.create` | A pending invite is stored for an email address without an account | The email address | | `iam.org_invite.revoke` | A pending invite is canceled | The invite ID | | `iam.service_account.create` | A service account is created | The service account’s principal | | `iam.service_account.revoke` | A service account is revoked | The service account’s principal | The audit log doesn’t record organization or project lifecycle changes, resource changes such as launching an instance, or refused requests. Writing an entry never blocks the change itself: if an entry can’t be written, the change still takes effect, so in rare cases an action is missing from the log. ## Entry fields [#entry-fields] Each entry has these fields. | Field | Description | | --- | --- | | `id` | Unique ID of the entry. | | `orgId` | The organization the action happened in. | | `projectId` | The project, for a project-scoped role assignment or revocation. Otherwise `null`. | | `actor` | The principal that performed the action. | | `action` | The action key from the table above. | | `target` | What the action was applied to, as listed in the table above. | | `outcome` | `SUCCESS` for every recorded action. | | `occurredAt` | When the action happened, as an RFC 3339 timestamp. | | `details` | Action-specific context as a JSON string, for example the role URN that was assigned. | ## Who can read it [#who-can-read-it] Reading the audit log requires the `iam.audit_log.list` permission on the organization. Both `roles/owner` and `roles/viewer` include it, assigned org-wide. See [Built-in roles](/docs/iam/roles). ## Paging through the log [#paging-through-the-log] `auditLogEntries` returns one page of entries, newest first, with a stable order for entries recorded at the same moment. You can read the whole organization’s log, or narrow it to the entries of one project with `projectId`. Only project-scoped role assignments and revocations carry a project, so a narrowed query leaves out every other action. The page tells you where you are: - `entries` – the entries on this page. - `total` – how many entries match your query across all pages. - `offset` and `limit` – the window you were actually served. - `hasMore` – `true` while entries remain beyond this page. When it’s `false`, you’ve read to the end. `limit` defaults to 100 and is capped at 500. If you ask for more than 500, you get 500, and the `limit` in the response says so. The cap applies to one page only; every entry is reachable by paging. To get the next page, add the served `limit` to `offset` and repeat while `hasMore` is `true`. The following steps show the paging loop. 1. Request the page with `offset` 0. 1. Process its entries, de-duplicating on `id`. 1. If `hasMore` is `true`, set `offset` to `offset` + `limit`, request the next page and repeat from step 2. If it’s `false`, you’ve read the whole log. The log is written while you read it. If new entries are recorded while you page through, they’re added at the front and shift older entries back, so an entry can appear on two consecutive pages. No entry is skipped. De-duplicate on `id` if you need each entry exactly once. ```graphql query { iam { auditLogEntries(input: { orgId: "", offset: 0, limit: 100 }) { entries { id actor action target outcome occurredAt details } total offset limit hasMore } } } ``` ## Related [#related] - [Assign and revoke roles](/docs/iam/assign-roles) - [Manage organization members](/docs/iam/manage-members) - [Use service accounts](/docs/iam/service-accounts) - [API access](/docs/platform/access/api) # Check access Look up who you are and which roles you hold, list the platform's permissions, and check whether a principal has a permission on a resource. You can check access before you act instead of handling a permission error afterward. This is useful in automation that needs to know whether a call will succeed, and when you investigate why a request was refused. ## Before you begin [#before-you-begin] - To see your own identity, grants and the list of permissions: any signed-in user or service account. - To list another principal’s roles: an org-wide `roles/owner` or `roles/viewer` assignment. - To check a permission with `has-permission`: `roles/owner` that covers the resource you check. ## Check who you are [#check-who-you-are] Show the signed-in user. The `userId` is what others use in `user:` to grant you a role. ```sh origin iam current-user ``` Example output (illustrative): ```json { "iam": { "currentUser": { "userId": "3f6e1c2a-8b4d-4e5f-9a1b-2c3d4e5f6a7b", "firstName": "Jane", "lastName": "Doe", "enabled": true, "email": "jane@example.com", "emailVerified": true } } } ``` ## List your own role assignments [#list-your-own-role-assignments] List every role assignment you hold, across all organizations you belong to. A `projectId` of `null` means the assignment is org-wide. ```sh origin iam current-user-grants ``` ## List another principal’s roles [#list-another-principals-roles] List every member of the organization with its role URNs, and find the principal in the output. ```sh origin iam list-members --org-id ``` To see each assignment’s project scope, list the principal’s grants. Each grant shows its project scope: ```sh origin iam principal-grants --org-id --principal ``` In the API, the `orgRoleAssignments` query returns the same scopes for the whole organization. See [Manage organization members](/docs/iam/manage-members). ## Find a permission key [#find-a-permission-key] List every permission the platform defines, with its service, resource type and action. ```sh origin iam permissions ``` For the permissions each role grants, see [Built-in roles](/docs/iam/roles). ## Check a permission on a resource [#check-a-permission-on-a-resource] 1. Get the URN of the resource you want to check. Every resource returns its URN in its `urn` field. 1. Check whether the principal holds the permission on that resource. ```sh origin iam has-permission \ --principal service_account: \ --permission-key compute.instance.launch \ --on-resource-urn ``` 1. Read the result: `true` means a request needing that permission on that resource is allowed; `false` means it would be refused. The check applies the same rules as a real request, including project scope. See [How a request is authorized](/docs/iam/access-model#how-a-request-is-authorized). ## Using the API [#using-the-api] The queries are `currentUser`, `currentUserGrants`, `orgMembers`, `orgRoleAssignments`, `permissions` and `hasPermission`, all in the `iam` namespace. ```graphql query { iam { hasPermission(input: { principal: "user:" permissionKey: "network.vpc.create" onResourceUrn: "" }) } } ``` ## Related [#related] - [Access model](/docs/iam/access-model) - [Built-in roles](/docs/iam/roles) - [`origin iam` commands](/docs/iam/reference/cli) # What is Origin Cloud IAM? IAM controls who can do what in your Origin Cloud organization. Learn how principals, roles, role assignments and permissions fit together. IAM (Identity and Access Management) controls who can do what in your organization. You give people and automation access by assigning them built-in roles, either across the whole organization or for one project. Every API request is checked against those assignments, so you can also ask in advance whether a request will be allowed. A principal is a user or a service account. A role assignment gives a principal one role, either org-wide or for a single project. The role is a fixed set of permissions, and each permission allows one action, such as `compute.instance.launch`, on resources inside the assignment's scope. For the details, see [Access model](/docs/iam/access-model). ## Features [#features] - **Built-in roles**: Owner, Viewer, IAM Editor and three billing roles, each with a fixed set of permissions. See [Built-in roles](/docs/iam/roles). - **Role assignments**: Grant a role to a user or service account org-wide or for one project, and revoke it again. See [Assign and revoke roles](/docs/iam/assign-roles). - **Organization members**: Invite people by email, list who has access, and remove a member's access in one step. See [Manage organization members](/docs/iam/manage-members). - **Service accounts**: Non-interactive credentials for CI pipelines, scripts and infrastructure-as-code tools, with their own principal and roles. See [Service accounts](/docs/iam/service-accounts). - **Access checks**: Look up your own grants, list available permissions, and check whether a principal holds a permission on a resource. See [Check access](/docs/iam/check-access). - **Audit log**: A record of who changed access in your organization and when. See [Audit log](/docs/iam/audit-log). ## Ways to access IAM [#ways-to-access-iam] - **CLI**: The `origin iam` command group. See [CLI access](/docs/platform/access/cli) to install and sign in, and [origin iam commands](/docs/iam/reference/cli) for every command. - **GraphQL API**: IAM queries and mutations live under the `iam` namespace of the API. See [API access](/docs/platform/access/api) and the [IAM reference](/docs/iam/reference) for the list of operations. ## Limitations [#limitations] - Custom roles aren't supported. You can assign and revoke the built-in roles only. - Groups aren't principals. The API lists three built-in groups by name and description, but you can't add members to a group or assign a role to one. - Role assignments are unconditional. You can't restrict a grant to a time window or an extra attribute check. - A service account's access is the union of its roles. You can't narrow one credential to a subset of what its roles allow. - Service accounts authenticate against the platform's own identity provider only. Federation with an external identity provider isn't supported. For quotas, see [Limits](/docs/platform/reference/limits). ## Related [#related] - [Organizations and projects](/docs/platform/organizations): the scopes that role assignments apply to - [Billing access](/docs/platform/billing/billing-access): who can see and change billing accounts - [CLI access](/docs/platform/access/cli): log in with `origin id login` ## Next steps [#next-steps] - Read the [Access model](/docs/iam/access-model) to understand scopes and permissions. - [Invite a member](/docs/iam/manage-members) to your organization. - [Create a service account](/docs/iam/service-accounts) for automation. # Manage organization members Invite people to your organization by email, list members and pending invites, remove a member's access, and cancel an invite before it applies. A member is any principal with at least one role assignment in your organization. You add people by email with an invite, which grants them one role org-wide. To change the roles of an existing member, [assign and revoke roles](/docs/iam/assign-roles). ## Before you begin [#before-you-begin] - To invite, remove or cancel an invite: an org-wide `roles/owner` assignment. You can only invite with a role you could assign yourself, and only remove a member whose every role you could revoke. See [Who can assign a role](/docs/iam/access-model#who-can-assign-a-role). - To list members and invites: an org-wide `roles/owner`, `roles/viewer` or `roles/iam/editor` assignment. - Your organization ID (``). ## Invite a member [#invite-a-member] 1. Find the URN of the role the new member should get with `list-roles`. See [Built-in roles](/docs/iam/roles). 1. Send the invite: ```sh origin iam invite-member --org-id \ --email jane@example.com \ --role-urn urn:origin:cloud:iam::::tc/role/roles/viewer ``` - Account exists: the role is granted org-wide immediately. There’s no separate step to accept. - No account yet: the invite is stored as pending. It’s applied the first time that address signs up and signs in to the console, or reads its own identity with `origin iam current-user`. If by then you can no longer assign the role yourself, the invite is dropped instead. 1. Verify the invite. An existing account appears in the member list; a pending invite appears in the invite list. ```sh origin iam list-members --org-id origin iam list-invites --org-id ``` Invites are org-wide only. To give someone access to a single project, ask them to sign up and send you the `userId` that `origin iam current-user` shows them. Then assign a project-scoped role to `user:`. ## List members and invites [#list-members-and-invites] - `list-members` shows every principal with an active role assignment, at any scope, with all of its role URNs. For users, it includes the name and email address where the platform can resolve them. Service accounts with roles appear here too. - `principal-grants` shows one principal’s role assignments, each with its project scope. - `list-invites` shows pending invites: the ID, email address, role URN, who invited them and when. An invite disappears from the list once it’s applied or canceled. ## Remove a member [#remove-a-member] Removing a member revokes every role the principal holds in the organization, org-wide and in every project. To take away a single role, [revoke the role](/docs/iam/assign-roles#revoke-a-role) instead. 1. Find the member’s principal in the output of `list-members`. 1. Remove the member. ```sh origin iam remove-member --org-id --principal user: ``` 1. Run `list-members` again and check that the principal is gone. Removing a principal that holds no roles succeeds and changes nothing. If the member is the organization’s last org-wide owner, the platform refuses with `CONFLICT` and removes nothing. See [The last owner is protected](/docs/iam/access-model#the-last-owner-is-protected). If the member holds a role you couldn’t revoke yourself, such as a billing role when you hold none, the platform refuses with `FORBIDDEN` and removes nothing. ## Cancel a pending invite [#cancel-a-pending-invite] `remove-member` acts only on role assignments, so it doesn’t cancel a pending invite. 1. Find the invite’s ID with `list-invites`. 1. Cancel the invite. ```sh origin iam revoke-invite --org-id --invite-id ``` 1. Run `list-invites` again and check that the invite is gone. ## Using the API [#using-the-api] The mutations are `inviteMember`, `removeMember` and `revokeInvite`; the queries are `orgMembers` and `orgInvites`, all in the `iam` namespace. `orgRoleAssignments` returns the same data as `orgMembers` with one entry per assignment, including its project scope and when it was created. For the full list, see the [IAM reference](/docs/iam/reference). ```graphql mutation { iam { inviteMember(input: { orgId: "" email: "jane@example.com" roleUrn: "urn:origin:cloud:iam::::tc/role/roles/viewer" }) } } ``` ## Related [#related] - [Assign and revoke roles](/docs/iam/assign-roles) - [Access model](/docs/iam/access-model) - [Organizations](/docs/platform/organizations) - [Audit log](/docs/iam/audit-log) – invites, cancellations and removals are recorded # origin iam commands Every origin iam command with its flags: members, invites, service accounts, role assignments and permission checks. This page lists every `origin iam` command. Logging in is `origin id login`; see [Use the CLI](/docs/platform/access/cli). ## invite-member [#invite-member] Invite a person to an org by email. Grants access immediately if they already have an account; otherwise stores a pending invite applied automatically the first time they authenticate. ```sh origin iam invite-member --org-id --email --role-urn ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--email ` | yes | Email address to invite. | | `--role-urn ` | yes | URN of the built-in role to grant once accepted. | ## remove-member [#remove-member] Remove a member’s access to an org - revokes every role they hold in it, at every project scope. ```sh origin iam remove-member --org-id --principal ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--principal ` | yes | The principal to remove, e.g. `user:` | ## revoke-invite [#revoke-invite] Cancel a pending invite before it’s been accepted. ```sh origin iam revoke-invite --org-id --invite-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--invite-id ` | yes | ID of the invite to revoke (see [`list-invites`](#list-invites)) | ## list-members [#list-members] List every principal with an active role assignment on an org. ```sh origin iam list-members --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## list-invites [#list-invites] List pending (not yet accepted) invites for an org. ```sh origin iam list-invites --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## create-service-account [#create-service-account] Create a service account for an organization. The response contains an OAuth client ID and client secret for the client-credentials grant; the secret is shown once, so store it now. The service account starts with no roles; grant it access with [`assign-role`](#assign-role). ```sh origin iam create-service-account --org-id --name ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--name ` | yes | Display name for the service account. | ## revoke-service-account [#revoke-service-account] Revoke a service account. Its credential stops working immediately: every request for a new access token is refused. An access token issued before the revocation stays valid until it expires. Its role assignments are kept; remove them with [`revoke-role`](#revoke-role). See [Service accounts](/docs/iam/service-accounts). ```sh origin iam revoke-service-account --org-id --service-account-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--service-account-id ` | yes | ID of the service account to revoke (see [`list-service-accounts`](#list-service-accounts)) | ## list-service-accounts [#list-service-accounts] List every service account (active or revoked) created for an org. ```sh origin iam list-service-accounts --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## assign-role [#assign-role] Assign a built-in role to a principal, org-wide or project-scoped. ```sh origin iam assign-role [OPTIONS] --org-id --principal --role-urn ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--project-id ` | no | Narrows the assignment to a single project. Omit for an org-wide grant. | | `--principal ` | yes | The principal to grant the role to, e.g. `user:` | | `--role-urn ` | yes | URN of the built-in role to assign. | ## revoke-role [#revoke-role] Revoke a previously assigned role from a principal. ```sh origin iam revoke-role [OPTIONS] --org-id --principal --role-urn ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--project-id ` | no | Must match the scope (org-wide vs. the given project) the role was originally assigned with. | | `--principal ` | yes | The principal to revoke the role from, e.g. `user:` | | `--role-urn ` | yes | URN of the role to revoke. | ## current-user [#current-user] Show the currently authenticated user. ```sh origin iam current-user ``` This command takes no options. ## current-user-grants [#current-user-grants] List the currently authenticated user’s role grants. ```sh origin iam current-user-grants ``` This command takes no options. ## principal-grants [#principal-grants] List every role a principal holds in an org, with each grant’s project scope. ```sh origin iam principal-grants --org-id --principal ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--principal ` | yes | The principal to look up, e.g. `user:` | ## list-roles [#list-roles] List the built-in roles available in an organization. ```sh origin iam list-roles --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## get-role [#get-role] Get a single built-in role and its permissions. ```sh origin iam get-role --role-urn ``` | Option | Required | Description | | --- | --- | --- | | `--role-urn ` | yes | URN of the role. | ## permissions [#permissions] List every permission the platform knows about. ```sh origin iam permissions ``` This command takes no options. ## has-permission [#has-permission] Check whether a principal has a given permission on a resource. ```sh origin iam has-permission --on-resource-urn --principal --permission-key ``` | Option | Required | Description | | --- | --- | --- | | `--on-resource-urn ` | yes | URN of the resource to check the permission against. | | `--principal ` | yes | The principal to check, e.g. `user:` | | `--permission-key ` | yes | Permission key to check, e.g. `network.vpc.list` | # IAM reference Where to find every origin iam command and built-in role, and a one-line summary of each IAM query and mutation in the GraphQL API. Look up exact commands, roles and API operations here. For how IAM works, see [Access model](/docs/iam/access-model). ## Reference pages [#reference-pages] | Page | What it lists | | --- | --- | | [CLI commands](/docs/iam/reference/cli) | Every `origin iam` command with its options. See [`origin iam` commands](/docs/iam/reference/cli). | | [Built-in roles](/docs/iam/roles) | Every role with its URN and permissions. See [Built-in roles](/docs/iam/roles). | | [Errors](/docs/platform/reference/errors) | Error codes shared by every API operation. See [Errors](/docs/platform/reference/errors). | ## GraphQL queries [#graphql-queries] All queries are fields of the `iam` namespace of the query root. | Query | Returns | | --- | --- | | `currentUser` | The signed-in user. | | `currentUserGrants` | Every role assignment the caller holds, in all organizations. | | `principalGrants` | Every role assignment one principal holds in the organization, with its scope and creation time. Needs `iam.member.list`, like `orgRoleAssignments`. | | `roles` | Every built-in role with its permissions. | | `role` | One built-in role by the URN `roles` lists. Needs no permission. | | `groups` | The three built-in groups, by name and description. Groups aren’t principals and can’t hold roles. | | `group` | One built-in group by URN, with your organization ID in it: `urn:origin:cloud:iam::::tc/group/`. | | `permissions` | Every permission the platform defines. | | `hasPermission` | Whether a principal holds a permission on a resource. | | `orgMembers` | Every principal with a role assignment in the organization, with its role URNs. | | `orgRoleAssignments` | Every role assignment in the organization, with its scope and creation time. | | `orgInvites` | Pending invites in the organization. | | `serviceAccounts` | Every service account in the organization, active or revoked, without secrets. | | `auditLogEntries` | One page of the organization’s audit log. See [Audit log](/docs/iam/audit-log). | ## GraphQL mutations [#graphql-mutations] All mutations are fields of the `iam` namespace of the mutation root. | Mutation | Effect | | --- | --- | | `assignRole` | Assigns a built-in role to a principal, org-wide or for one project. Only a role whose permissions you hold yourself at that scope. | | `revokeRole` | Revokes one role from a principal at exactly the given scope. Only a role whose permissions you hold yourself at that scope. | | `inviteMember` | Invites a person by email with one org-wide role, which you must be able to assign. | | `removeMember` | Revokes every role a principal holds in the organization, if you could revoke each of them. | | `revokeInvite` | Cancels a pending invite. | | `createServiceAccount` | Creates a service account and returns its client ID and one-time client secret. | | `revokeServiceAccount` | Disables a service account’s credential. | ## Example: list one principal’s grants [#example-list-one-principals-grants] `principalGrants` takes its arguments in an `input` object with `orgId` and `principal`. This form replaced a bare `principal` argument on 12 October 2026, without a deprecation period. A grant whose `projectId` is `null` is org-wide. ```graphql query { iam { principalGrants(input: { orgId: "" principal: "user:" }) { urn projectId roles { roleUrn } createdAt createdBy } } } ``` The CLI equivalent is `origin iam principal-grants --org-id --principal `. # Built-in roles Every built-in IAM role with its ID, URN, what it's for and the exact permissions it grants, including the billing roles that Owner doesn't include. Origin Cloud has six built-in roles. You can’t create your own. Each section lists the role’s ID, the URN you pass to role commands, where you can assign it, and every permission it grants. Permission keys have the form `..`; the tables group them by `.`. For how roles, scopes and permissions work together, see [Access model](/docs/iam/access-model). | ID | Name | For | | --- | --- | --- | | [`roles/owner`](#rolesowner) | Owner | Full control of the organization, except billing accounts | | [`roles/viewer`](#rolesviewer) | Viewer | Read-only access to everything Owner can change | | [`roles/iam/editor`](#rolesiameditor) | IAM Editor | Assigning and revoking roles within its own permissions | | [`roles/billing/administrator`](#rolesbillingadministrator) | Billing Account Administrator | Full control of billing accounts | | [`roles/billing/user`](#rolesbillinguser) | Billing Account User | Billing accounts without deleting them | | [`roles/billing/viewer`](#rolesbillingviewer) | Billing Account Viewer | Read-only access to billing accounts | ## roles/owner [#rolesowner] Full control of the organization’s projects, resources and access. Owner doesn’t include any billing account permission: an Owner can switch which billing account a project is charged to (`admin.project.attach`) and manage spend limits, but can’t view, create, change or delete a billing account. For that, assign a billing role; see [Billing access](/docs/platform/billing/billing-access). **URN:** `urn:origin:cloud:iam::::tc/role/roles/owner` **Scope:** org-wide or one project. Only an org-wide Owner can manage members and service accounts. Because Owner holds no billing permission, an Owner can’t assign or revoke the billing roles unless it also holds `roles/billing/administrator`. | Resource | Actions | | --- | --- | | `admin.organisation` | `get`, `list`, `update`, `create`, `delete` | | `admin.project` | `get`, `list`, `update`, `create`, `delete`, `attach` | | `admin.resource_quota` | `get`, `update` | | `admin.spend_limit` | `get`, `update` | | `admin.support_case` | `list`, `get`, `create`, `update` | | `admin.usage` | `list` | | `compute.image` | `get`, `list`, `create`, `delete`, `update` | | `compute.instance` | `get`, `list`, `update`, `launch`, `terminate`, `start`, `stop`, `attach`, `detach` | | `compute.key_pair` | `get`, `list`, `create`, `delete` | | `iam.audit_log` | `list` | | `iam.group` | `get`, `list`, `update`, `create`, `delete` | | `iam.member` | `list`, `create`, `revoke` | | `iam.permission` | `query` | | `iam.role` | `get`, `list`, `update`, `create`, `delete`, `assign`, `revoke` | | `iam.service_account` | `list`, `create`, `revoke` | | `network.acl` | `get`, `list`, `create`, `update`, `delete` | | `network.dns_policy` | `get`, `list`, `create`, `update`, `set_default`, `delete`, `attach` | | `network.floating_ip` | `get`, `list`, `create`, `attach`, `detach`, `delete` | | `network.interface` | `get`, `list`, `create`, `delete`, `attach` | | `network.internet_gateway` | `get`, `attach`, `detach` | | `network.nat_gateway` | `get`, `list`, `create`, `delete` | | `network.route_table` | `get`, `list`, `create`, `update`, `delete` | | `network.security_group` | `get`, `list`, `create`, `update`, `delete` | | `network.subnet` | `get`, `list`, `create`, `update`, `delete` | | `network.vpc` | `get`, `list`, `create`, `delete` | | `observability.metric` | `get` | | `pvs.snapshot` | `get`, `list`, `create`, `delete`, `update`, `protect`, `unprotect` | | `pvs.volume` | `get`, `list`, `create`, `delete`, `update` | Some keys are reserved: no operation uses them yet. Built-in roles and groups can’t be created, changed or deleted, so the `create`, `update` and `delete` actions on `iam.role` and `iam.group` allow nothing today. ## roles/viewer [#rolesviewer] Read-only access: every `get` and `list` permission that Owner holds. A Viewer can list members, pending invites, service accounts and the audit log, but can’t change anything. Viewer includes no billing account permission. **URN:** `urn:origin:cloud:iam::::tc/role/roles/viewer` **Scope:** org-wide or one project. | Resource | Actions | | --- | --- | | `admin.organisation` | `get`, `list` | | `admin.project` | `get`, `list` | | `admin.resource_quota` | `get` | | `admin.spend_limit` | `get` | | `admin.support_case` | `list`, `get` | | `admin.usage` | `list` | | `compute.image` | `get`, `list` | | `compute.instance` | `get`, `list` | | `compute.key_pair` | `get`, `list` | | `iam.audit_log` | `list` | | `iam.group` | `get`, `list` | | `iam.member` | `list` | | `iam.role` | `get`, `list` | | `iam.service_account` | `list` | | `network.acl` | `get`, `list` | | `network.dns_policy` | `get`, `list` | | `network.floating_ip` | `get`, `list` | | `network.interface` | `get`, `list` | | `network.internet_gateway` | `get` | | `network.nat_gateway` | `get`, `list` | | `network.route_table` | `get`, `list` | | `network.security_group` | `get`, `list` | | `network.subnet` | `get`, `list` | | `network.vpc` | `get`, `list` | | `observability.metric` | `get` | | `pvs.snapshot` | `get`, `list` | | `pvs.volume` | `get`, `list` | ## roles/iam/editor [#rolesiameditor] Lets a principal list members and roles, and assign and revoke roles in the organization. An IAM Editor can’t invite or remove members or manage service accounts; those need Owner. An IAM Editor can only hand out what it already has. Like every principal, it can assign or revoke a role only if it holds every permission of that role itself at the scope of the grant; see [Who can assign a role](/docs/iam/access-model#who-can-assign-a-role). With IAM Editor alone, that is IAM Editor itself. To let it assign Viewer as well, assign it Viewer too. An IAM Editor can never make anyone an Owner, itself included. **URN:** `urn:origin:cloud:iam::::tc/role/roles/iam/editor` **Scope:** org-wide. Role operations act on the organization, so a project-scoped IAM Editor can’t use them. | Resource | Actions | | --- | --- | | `iam.member` | `list` | | `iam.role` | `get`, `list`, `assign`, `revoke` | ## roles/billing/administrator [#rolesbillingadministrator] Full control of the organization’s billing accounts: view, create, update and delete them. Whoever creates an organization holds this role org-wide. **URN:** `urn:origin:cloud:iam::::tc/role/roles/billing/administrator` **Scope:** org-wide only. Assign it without a project. | Resource | Actions | | --- | --- | | `admin.billing_account` | `get`, `list`, `create`, `update`, `delete` | ## roles/billing/user [#rolesbillinguser] Everything the Billing Account Administrator can do, except deleting a billing account. **URN:** `urn:origin:cloud:iam::::tc/role/roles/billing/user` **Scope:** org-wide only. Assign it without a project. | Resource | Actions | | --- | --- | | `admin.billing_account` | `get`, `list`, `create`, `update` | ## roles/billing/viewer [#rolesbillingviewer] Read-only access to the organization’s billing accounts. **URN:** `urn:origin:cloud:iam::::tc/role/roles/billing/viewer` **Scope:** org-wide only. Assign it without a project. | Resource | Actions | | --- | --- | | `admin.billing_account` | `get`, `list` | ## Related [#related] - [Access model](/docs/iam/access-model) - [Assign and revoke roles](/docs/iam/assign-roles) - [Billing access](/docs/platform/billing/billing-access) - [`list-roles`](/docs/iam/reference/cli#list-roles) and [`permissions`](/docs/iam/reference/cli#permissions) commands # Use service accounts Create a service account for CI and scripts, exchange its client ID and secret for an access token, grant it roles, and revoke it. A service account is a non-interactive credential for automation such as CI pipelines, scripts and infrastructure-as-code tools. It belongs to one organization and acts as its own principal, `service_account:`. Its access is checked exactly like a user’s: it can do what its role assignments allow, and nothing else. A service account authenticates with an OAuth 2.0 client ID and client secret, using the client credentials grant against the platform’s identity provider. The resulting access token is sent to the API like a user’s. ## Before you begin [#before-you-begin] - To create or revoke a service account: an org-wide `roles/owner` assignment. - To list service accounts: an org-wide `roles/owner` or `roles/viewer` assignment. - Your organization ID (``). ## Create a service account [#create-a-service-account] 1. Create the service account with a name that tells you what uses it. ```sh origin iam create-service-account --org-id --name ci-deploy ``` The output contains the service account’s `id`, its `principal`, and the credential: `clientId` and `clientSecret`. The client secret is shown only once. Store it in your secret manager now. No API returns it again; if you lose it, create a new service account. 1. Grant the service account the roles it needs. A new service account holds no roles and can’t do anything until you assign one. Use the `principal` from the previous step. ```sh origin iam assign-role --org-id \ --project-id \ --principal service_account: \ --role-urn urn:origin:cloud:iam::::tc/role/roles/viewer ``` Grant the smallest role and scope that does the job. See [Assign and revoke roles](/docs/iam/assign-roles). 1. Verify that the service account is listed as active. An active service account has no `revokedAt` value. ```sh origin iam list-service-accounts --org-id ``` ## Get an access token [#get-an-access-token] The `origin` CLI logs in people only. Automation that runs as a service account calls the GraphQL API directly. 1. Request an access token from the token endpoint with the client credentials grant. ```sh curl -s \ https://auth.origincloud.eu/realms/origincloud/protocol/openid-connect/token \ -d grant_type=client_credentials \ -d client_id= \ -d client_secret= ``` The response is JSON with an `access_token` and its lifetime in seconds, `expires_in`. Request a new token when it expires. 1. Send the token as a bearer token with each API request. ```sh curl -s https://api.origincloud.eu/graphql \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"query":"{ iam { permissions { key } } }"}' ``` 1. Verify that the token is accepted: the response contains a `data` object rather than an authentication error. ## Revoke a service account [#revoke-a-service-account] Revoking a service account disables its credential. From that moment, every request for a new access token is refused. An access token issued before the revocation stays valid until it expires. 1. Find the service account’s ID with `list-service-accounts`. 1. Revoke it. ```sh origin iam revoke-service-account --org-id \ --service-account-id ``` 1. Revoke its role assignments as well. Revoking the service account leaves them in place, and removing them cuts off any access token that is still valid, because roles are checked on every request. ```sh origin iam remove-member --org-id \ --principal service_account: ``` 1. Run `list-service-accounts` again and check that the service account has a `revokedAt` time. Revoked service accounts stay in the list. A revoked service account can’t be reactivated. ## Rotate a client secret [#rotate-a-client-secret] A client secret can’t be changed or shown again. To rotate it, replace the service account with a new one: 1. Create a new service account, as in [Create a service account](#create-a-service-account), and store its client secret. 1. List the old service account’s role assignments, with their project scope: ```sh origin iam principal-grants --org-id \ --principal service_account: ``` 1. Assign the same roles, at the same scopes, to the new service account’s principal with `origin iam assign-role`. 1. Switch your automation to the new client ID and secret. 1. Revoke the old service account and remove its role assignments, as in [Revoke a service account](#revoke-a-service-account). ## Using the API [#using-the-api] The mutations are `createServiceAccount` and `revokeServiceAccount`; the query is `serviceAccounts`, all in the `iam` namespace. `serviceAccounts` never returns a client secret. ```graphql mutation { iam { createServiceAccount(input: { orgId: "", name: "ci-deploy" }) { id principal clientId clientSecret } } } ``` ## Related [#related] - [Access model](/docs/iam/access-model) - [Built-in roles](/docs/iam/roles) - [API access](/docs/platform/access/api) - [`create-service-account`](/docs/iam/reference/cli#create-service-account) and [`revoke-service-account`](/docs/iam/reference/cli#revoke-service-account) commands - [Audit log](/docs/iam/audit-log) – creation and revocation are recorded # Origin Cloud Docs User documentation for Origin Cloud, for anyone calling the GraphQL API or the origin CLI. } > What the platform can do, written for someone calling the GraphQL API or the `origin` CLI, not for someone reading the source. Every page says what kind it is (overview, concept, task, reference, troubleshooting or tutorial), so you know whether to read or to do. Start here: Get started with Origin Cloud Use the GraphQL API ## Guides [#guides] Ways to access Origin Cloud → The origin CLI and the GraphQL API, side by side. Then clean up. You pay for a few minutes of one gp1.core.2 instance, its volume and its public address. Every code, refusal or fault, retryable or not, and what to do. Organization quotas, project budgets and the platform's hard limits. One page per guide's Reference group. The five metrics and the metrics query. GET /v1/pricing: public, no token, ETag. Failed instances, refused launches and starts, SSH that won't connect. Volumes in ERROR, failed resizes, refused deletes, failed imports. No internet access, refused requests, connections that hang. Search covers every page. Each result shows its kind and the guide it belongs to. # DNS Every instance gets an internal hostname that its VPC resolves, and DNS policies decide where other queries go. Learn how names are resolved in a VPC. Instances in the same VPC can resolve each other by hostname without any setup. Every subnet has a DNS resolver on its second address after the network address, and every instance uses it. The resolver answers names in its own VPC itself, and relays every other query according to the VPC’s DNS policy. The resolver handles a query from an instance like this: 1. If the hostname is in this VPC, the resolver answers. 2. If not, and the DNS policy relays, the upstream servers answer. 3. If not, and the DNS policy doesn’t relay, the query is refused. ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Internal hostname | Every instance has a hostname derived from its primary private IPv4 address in the `internal` domain. An instance at `10.0.1.20` answers to `ip-10-0-1-20.internal`. Because `internal` is on every instance’s DNS search list, the short name `ip-10-0-1-20` works too. | | Per-VPC resolution | Each VPC resolves only its own instances’ hostnames. Two instances in different VPCs can have the same hostname without conflict, and neither VPC can resolve the other’s. | | DNS policy | Decides what happens to queries the resolver can’t answer itself: whether they’re relayed at all, and to which upstream servers. A DNS policy belongs to a project, not to one VPC. A project can have several, and one policy can serve several VPCs. If a policy has relaying turned off, every query outside the VPC is refused. | | Default policy | Each project has exactly one default policy. The platform creates it with your first VPC in the project, pointing at a public resolver with relaying on. Every VPC you create attaches to the project’s default policy at the time. | ## What you can do [#what-you-can-do] - [Manage DNS policies](/docs/network/dns/manage-policies): create policies, change their servers, attach one to a VPC, change the project default, delete one. ## Related [#related] - [VPC and subnet addressing](/docs/network/vpcs/addressing) - [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets) - [origin network commands](/docs/network/reference/cli) # Manage DNS policies Create DNS policies, change their upstream servers and relaying, attach a policy to a VPC, change a project's default policy, and delete a policy. A DNS policy decides where a VPC relays queries it can’t answer itself. Use your own policy when a VPC must resolve names in your company’s DNS zone, or when it must not resolve external names at all. ## Before you begin [#before-you-begin] - The URN of the project, and of the VPC if you attach a policy to one. - The IPv4 or IPv6 addresses of the upstream DNS servers you want to use. ## Create a policy [#create-a-policy] 1. Create the policy with its upstream servers and relaying turned on: ```sh origin network create-dns-policy --project-urn \ --relay-enabled true \ --upstream-server 192.0.2.53 --upstream-server 192.0.2.54 ``` To create a policy that refuses every query outside the VPC, use `--relay-enabled false --no-upstream-servers`. Relaying with no upstream servers is refused. 1. Verify it with `list-dns-policies --project-urn `. ## Attach a policy to a VPC [#attach-a-policy-to-a-vpc] 1. Attach the policy. It must belong to the VPC’s project. ```sh origin network attach-dns-policy --vpc-urn \ --dns-policy-urn ``` 1. Verify that the VPC’s `dnsPolicyId` names the policy: ```sh origin network get-vpc --vpc-urn ``` ## Change a policy’s servers or relaying [#change-a-policys-servers-or-relaying] 1. Send the policy’s full new settings. The server list you give replaces the existing one. ```sh origin network update-dns-policy --dns-policy-urn \ --relay-enabled true --upstream-server 192.0.2.53 ``` 1. Verify with `get-dns-policy --dns-policy-urn `. The change applies to every VPC attached to the policy while instances keep running; no restart is needed. ## Change the project’s default policy [#change-the-projects-default-policy] 1. Make another policy the default: ```sh origin network set-default-dns-policy --dns-policy-urn ``` 1. Verify with `list-dns-policies`. Only VPCs you create afterwards attach to the new default. Existing VPCs keep their current policy; use [`attach-dns-policy`](/docs/network/reference/cli#attach-dns-policy) to move them. ## Delete a policy [#delete-a-policy] 1. Attach every VPC that uses the policy to another one. A policy can’t be deleted while a VPC is attached to it, or while it’s the project’s default. 1. Delete the policy: ```sh origin network delete-dns-policy --dns-policy-urn ``` 1. Verify that `list-dns-policies` no longer shows it. Deleting a VPC doesn’t delete its DNS policy. ## Related [#related] - [DNS](/docs/network/dns) - [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets) - [`create-dns-policy` reference](/docs/network/reference/cli#create-dns-policy) - [`update-dns-policy` reference](/docs/network/reference/cli#update-dns-policy) - [`attach-dns-policy` reference](/docs/network/reference/cli#attach-dns-policy) # What is Origin Cloud Network? Network gives your instances private VPCs, subnets and network interfaces, controlled internet access, traffic filtering and DNS. Learn how the parts fit. Network is where your instances live. A VPC is an isolated network with its own private address space, subnets divide that space, and every instance connects to a subnet through a network interface. A VPC you create is private: nothing in it is reachable from the internet until you attach an Internet Gateway and give instances a way out. Your project's [default VPC](/docs/network/vpcs/default-vpc) is different: it comes with an Internet Gateway, and an instance launched into it gets a public address automatically. Security groups and network ACLs decide which traffic is allowed, and a DNS policy decides how the VPC resolves names it doesn't know. An instance's network interface holds its private IPv4 and IPv6 addresses in one subnet. A Floating IP gives one interface a public IPv4 address. A NAT gateway gives a whole subnet outbound-only internet access through one shared address. ## Features [#features] - **VPCs and subnets**: Isolated networks with a private IPv4 range you choose or the platform picks, an IPv6 range assigned for you, and subnets carved from both. Every project also gets a default VPC the first time it needs one. See [VPCs and subnets](/docs/network/vpcs). - **Internet access**: Internet Gateways, route tables, NAT gateways and Floating IPs decide whether and how traffic reaches the internet. See [Internet access](/docs/network/internet-access). - **Traffic control**: Stateful security groups on each network interface and stateless network ACLs on each subnet. See [Traffic control](/docs/network/traffic-control). - **DNS**: Every instance gets an internal hostname that other instances in its VPC can resolve. DNS policies decide where other queries are relayed. See [DNS](/docs/network/dns). ## Ways to access Network [#ways-to-access-network] - **CLI**: The `origin network` command group. See [CLI access](/docs/platform/access/cli) to install and sign in, and [origin network commands](/docs/network/reference/cli) for every command. - **GraphQL API**: VPCs, subnets, network interfaces, gateways, route tables, Floating IPs, ACLs, security groups and DNS policies live under the `network` namespace of the API, for both queries and mutations. See [API access](/docs/platform/access/api) and the [Network reference](/docs/network/reference). ## When to use Network [#when-to-use-network] Every instance needs a subnet, so you use Network whenever you run Compute. Create your own VPCs when you want to choose the address range, keep workloads apart, or decide yourself which subnets reach the internet. If you launch without naming a subnet, the platform uses your project's [default VPC](/docs/network/vpcs/default-vpc). Network doesn't connect two VPCs to each other, and it doesn't give instances IPv6 internet access. Traffic between the internet and your instances is IPv4 only, through a Floating IP or a NAT gateway. ## Related services [#related-services] - [Compute](/docs/compute): instances that connect to subnets through network interfaces - [Platform](/docs/platform): organizations, projects, billing and access ## Pricing [#pricing] VPCs, subnets, route tables, ACLs, security groups and DNS policies cost nothing by themselves. Floating IPs and NAT gateways are billed while you hold them, and traffic from your VPC to the internet is billed. Allocating a Floating IP and creating a NAT gateway require a payment method; see [Add a payment method](/docs/platform/billing/payment-method). For prices, see [Pricing](/docs/pricing). ## Next steps [#next-steps] - [Get started with Origin Cloud](/docs/platform/getting-started) - [Create a VPC and subnets](/docs/network/vpcs/create) - [Give a private subnet internet access with a NAT gateway](/docs/network/internet-access/nat-gateways) - [Troubleshoot Network](/docs/network/troubleshooting) # Floating IPs A Floating IP is a public IPv4 address you hold and associate with a network interface. Learn how to use it, when it's released, and how it behaves inside its VPC. A Floating IP is a public IPv4 address that you allocate to a project and associate with a network interface. The platform translates it 1:1 to the interface’s private IPv4 address, in both directions: the instance reaches the internet as that address, and the internet reaches the instance through it. The address stays yours, unassociated if need be, until you release it. The states of a Floating IP you allocate: | From | Command or event | To | | --- | --- | --- | | – | `allocate-floating-ip` | unassociated | | unassociated | `associate-floating-ip` | associated | | associated | `disassociate-floating-ip`, or the instance is terminated | unassociated | | unassociated | `release-floating-ip` | released | ## Use a Floating IP [#use-a-floating-ip] You work with a Floating IP through four commands: - [`allocate-floating-ip`](/docs/network/reference/cli#allocate-floating-ip) takes an address from the platform’s public pool for your project. It requires a payment method; without one, it’s refused with `PAYMENT_METHOD_REQUIRED`. - [`associate-floating-ip`](/docs/network/reference/cli#associate-floating-ip) points it at a network interface. A Floating IP serves one interface at a time; associating one that’s already associated is refused. - [`disassociate-floating-ip`](/docs/network/reference/cli#disassociate-floating-ip) removes the association. Running it on an unassociated address does nothing. - [`release-floating-ip`](/docs/network/reference/cli#release-floating-ip) gives the address back. It’s refused while the address is associated. For example, to give a running instance a public address, find its interface with `list-network-interfaces` and run: ```sh origin network associate-floating-ip --floating-ip-urn \ --network-interface-urn ``` The instance’s subnet must be in a VPC with an Internet Gateway, and its security groups and network ACL must allow the traffic. See [Internet access](/docs/network/internet-access). ## When an address is released [#when-an-address-is-released] An address you allocated is never released for you. Terminating the instance it’s associated with only disassociates it, so it’s ready for the next instance. An address the platform assigned at launch, because the subnet has auto-assign public IP turned on, is different: the platform releases it when you terminate the instance. To keep an address across instances, allocate one yourself. See [Default VPC](/docs/network/vpcs/default-vpc). A released address isn’t allocated again for one hour, whether you released it or the platform did. DNS records, allow-lists and integrations that still name the address have that hour to expire or be updated before the address can belong to someone else. For the same reason, an address you’re allocated wasn’t someone else’s a moment ago. ## Reaching a Floating IP from inside its VPC [#reaching-a-floating-ip-from-inside-its-vpc] An instance can connect to the Floating IP of another instance in the same VPC, or to its own, and gets the reply from that Floating IP. This happens when services in one VPC address each other by public DNS name, or when an instance checks itself through its public address. Two things differ from private-address traffic: - The server sees a public source address. A caller with its own Floating IP appears as that address. A caller without one appears as the Floating IP it called. Security group rules that name a group, including the default group’s rule, match private addresses only, so they don’t admit this traffic and the connection hangs. Allow the port from the public addresses you expect, as you would for an external client. - It works only from the Floating IP’s own VPC. From an instance in a different VPC, even one of yours, connecting to a Floating IP hangs. Reach that instance from outside the platform instead. ## When no address is available [#when-no-address-is-available] The public IPv4 pool is shared by the whole platform, so `allocate-floating-ip` can be refused because no address is left. That’s separate from your organization’s and project’s public IP quota, which is refused with the limit you reached. Both messages say which one applies. Releasing Floating IPs you don’t need frees quota and pool space. ## Billing [#billing] A Floating IP is billed for as long as it’s allocated to you, whether or not it’s associated. For prices, see [Pricing](/docs/pricing). ## Related [#related] - [Give a private subnet internet access with a NAT gateway](/docs/network/internet-access/nat-gateways) - [Network interfaces](/docs/network/vpcs/network-interfaces) - [`allocate-floating-ip` reference](/docs/network/reference/cli#allocate-floating-ip) - [`associate-floating-ip` reference](/docs/network/reference/cli#associate-floating-ip) - [Limits](/docs/platform/reference/limits) # Internet access How traffic gets between your instances and the internet - Internet Gateways, route tables, NAT gateways and Floating IPs, and the two paths they form. A VPC you create is private: nothing in it reaches the internet or can be reached from it. Internet access takes an Internet Gateway on the VPC, plus one of two ways out for each instance. A Floating IP gives one instance a public IPv4 address in both directions. A NAT gateway gives a whole subnet outbound-only access through one shared address. The two paths from an instance to the internet: - **Instance with a Floating IP:** the Floating IP (1:1 NAT), then the Internet Gateway, then the internet. - **Instance without a Floating IP:** the subnet’s route table (`0.0.0.0/0`), then a NAT gateway in a public subnet, then the Internet Gateway, then the internet. Internet traffic is IPv4 only. Instances can’t use IPv6 to or from the internet; see [VPC and subnet addressing](/docs/network/vpcs/addressing). An instance with a Floating IP always uses it, even in a subnet routed through a NAT gateway. An instance with neither has no internet access. On both paths, the subnet’s network ACL and the instance’s security groups must also allow the traffic; see [Traffic control](/docs/network/traffic-control). ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Internet Gateway | Connects a whole VPC to the internet. A VPC has at most one. Attaching it adds a default route through it to the VPC’s main route table. See [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). | | Route table | Decides where a subnet’s internet-bound traffic goes: out through the Internet Gateway, through a NAT gateway, or nowhere. Every VPC has a main table, and you can add more. See [Route tables](/docs/network/internet-access/route-tables). | | Floating IP | A public IPv4 address you hold in your project and associate with a network interface. The platform translates it 1:1 to the interface’s private address. See [Floating IPs](/docs/network/internet-access/floating-ips). | | NAT gateway | Shared outbound IPv4 access for instances without a Floating IP. Instances behind it aren’t reachable from the internet. See [Give a private subnet internet access with a NAT gateway](/docs/network/internet-access/nat-gateways). | ## What you can do [#what-you-can-do] - [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways) - [Give a private subnet internet access with a NAT gateway](/docs/network/internet-access/nat-gateways) - [Allocate, associate and release Floating IPs](/docs/network/internet-access/floating-ips#use-a-floating-ip) ## Limits and quotas [#limits-and-quotas] Internet Gateways, NAT gateways and public IPv4 addresses are limited per organization and project. See [Limits](/docs/platform/reference/limits). ## Related [#related] - [VPCs and subnets](/docs/network/vpcs) - [Traffic control](/docs/network/traffic-control) - [Troubleshoot Network](/docs/network/troubleshooting) # Attach and detach an Internet Gateway Attach an Internet Gateway to connect a whole VPC to the internet, check it, and detach it again to make the VPC private. An Internet Gateway connects a whole VPC to the internet, including subnets and instances you create after attaching it. There is no per-subnet switch; you decide per subnet through route tables, Floating IPs and NAT gateways. A VPC has at most one Internet Gateway. ## Before you begin [#before-you-begin] - The URN of the VPC. - Room in your organization’s Internet Gateway quota. See [Limits](/docs/platform/reference/limits). ## Attach an Internet Gateway [#attach-an-internet-gateway] 1. Attach the gateway: ```sh origin network attach-internet-gateway --vpc-urn ``` The platform creates the gateway and adds two default routes through it to the VPC’s main route table: `0.0.0.0/0` and `::/0`. If the VPC already has a gateway, the command returns the existing one, unless your organization is at its Internet Gateway quota, in which case it’s refused. 1. Verify the gateway: ```sh origin network get-internet-gateway --vpc-urn ``` 1. Check that the main route table has the default routes. Find the table with `list-route-tables`, then: ```sh origin network get-route-table --route-table-urn ``` Attaching the gateway makes internet access possible; it doesn’t give it to any instance by itself. An instance also needs a Floating IP or a NAT gateway route, and its network ACL and security groups must allow the traffic. See [Internet access](/docs/network/internet-access). Attaching a gateway also lets instances in different subnets of the VPC reach each other, because traffic between subnets goes through the VPC router that the gateway enables. ## Detach an Internet Gateway [#detach-an-internet-gateway] 1. Remove routes through the gateway from every route table other than the main one. Detaching is refused while another table still routes through it. For how to edit routes, see [Route tables](/docs/network/internet-access/route-tables). 1. Detach the gateway: ```sh origin network detach-internet-gateway --vpc-urn ``` The platform removes the main route table’s routes through the gateway for you. Detaching from a VPC with no gateway does nothing. 1. Verify that `get-internet-gateway` returns no gateway for the VPC. After detaching, nothing in the VPC reaches the internet, and instances in different subnets can no longer reach each other. A route can’t name a detached gateway. If you attach a new gateway later, the main table gets new default routes, and other tables must name the new gateway. ## Related [#related] - [Route tables](/docs/network/internet-access/route-tables) - [`attach-internet-gateway` reference](/docs/network/reference/cli#attach-internet-gateway) - [`detach-internet-gateway` reference](/docs/network/reference/cli#detach-internet-gateway) # Give a private subnet internet access with a NAT gateway Create a NAT gateway so instances without a Floating IP can reach the internet over IPv4, route a private subnet through it, and delete it again. A NAT gateway gives every instance in a private subnet outbound IPv4 access through one shared address. Instances behind it reach the internet as the gateway’s address and aren’t reachable from the internet. Use it for instances that only need to fetch packages or call external services, instead of giving each one a Floating IP. A NAT gateway translates IPv4 only. It’s billed per hour, in addition to the Floating IP it uses. ## Before you begin [#before-you-begin] - A VPC with an Internet Gateway attached. See [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). - A public subnet for the gateway: one whose route table has a default route to the Internet Gateway. With the gateway attached, every subnet that uses the main table is public. - A private subnet for your instances, associated with a route table you created. See [Route tables](/docs/network/internet-access/route-tables). - A verified payment method on the billing account your project is charged to. See [Add a payment method](/docs/platform/billing/payment-method). Without one, allocating the Floating IP and creating the gateway are refused with `PAYMENT_METHOD_REQUIRED`. ## Create the NAT gateway [#create-the-nat-gateway] 1. Allocate a Floating IP for the gateway and leave it unassociated: ```sh origin network allocate-floating-ip --project-urn ``` The address stays yours when you delete the gateway later. 1. Create the gateway in the public subnet: ```sh origin network create-nat-gateway --subnet-urn \ --floating-ip-urn ``` The command is refused if the subnet isn’t public, if the Floating IP is associated with a network interface, if the Floating IP already backs another NAT gateway, or if you’re at your NAT gateway quota. 1. Note the gateway’s URN: ```sh origin network list-nat-gateways --project-urn ``` ## Route the private subnet through the gateway [#route-the-private-subnet-through-the-gateway] 1. Read the current routes of the private subnet’s route table: ```sh origin network get-route-table --route-table-urn ``` 1. Replace the routes with the existing local routes plus a `0.0.0.0/0` route to the gateway. The command replaces the whole list, so include every route you want to keep. ```sh origin network update-route-table-routes \ --route-table-urn \ --route '10.0.0.0/16,local' \ --route ',local' \ --route '0.0.0.0/0,nat-gateway,' ``` A `nat-gateway` route must have the destination `0.0.0.0/0`. A `::/0` or narrower destination is refused. 1. If the subnet doesn’t use this table, associate it: ```sh origin network associate-route-table --subnet-urn \ --route-table-urn ``` 1. Verify from an instance in the private subnet that it reaches the internet as the gateway’s address, for example by calling a service that shows the caller’s public address. The change applies to new connections within a few seconds. An instance in the private subnet that has its own Floating IP keeps using that address, not the gateway’s. ## Delete a NAT gateway [#delete-a-nat-gateway] 1. Remove or replace every route that names the gateway, in every route table. Deleting is refused while any route table still routes through it. 1. Delete the gateway: ```sh origin network delete-nat-gateway --nat-gateway-urn ``` 1. Verify that `list-nat-gateways` no longer shows it. Release the Floating IP with [`release-floating-ip`](/docs/network/reference/cli#release-floating-ip) if you don’t need it any more; billing for it continues until you do. A NAT gateway is never deleted with its subnet or VPC. Deleting a subnet or VPC is refused while a NAT gateway lives in it. ## Related [#related] - [Route tables](/docs/network/internet-access/route-tables) - [Floating IPs](/docs/network/internet-access/floating-ips) - [`create-nat-gateway` reference](/docs/network/reference/cli#create-nat-gateway) - [`delete-nat-gateway` reference](/docs/network/reference/cli#delete-nat-gateway) - [Troubleshoot Network](/docs/network/troubleshooting) # Route tables How route tables decide where a subnet's internet traffic goes, how the main table differs from tables you create, and how to change routes and associations. A route table decides where a subnet’s internet-bound traffic goes. Every subnet uses exactly one table. Traffic between addresses inside the VPC doesn’t depend on route tables. ## Main table and tables you create [#main-table-and-tables-you-create] Every VPC has one main route table, created with the VPC. Every subnet uses it until you associate the subnet with another table. The main table starts with local routes for the VPC’s own IPv4 and IPv6 ranges. Attaching an Internet Gateway adds the default routes `0.0.0.0/0` and `::/0` through the gateway. A table you create with `create-route-table` starts with the VPC’s local routes and no default route. A subnet that uses it reaches its own VPC and nothing else, until you add a default route. This is how you make a private subnet next to a public one. A subnet is public when its route table has a default route to the Internet Gateway, and private otherwise. ## Routes and targets [#routes-and-targets] A route sends traffic for a destination range to a target: | Target | Meaning | | --- | --- | | `local` | The VPC itself. Names no resource. | | `internet-gateway` | Out through the VPC’s Internet Gateway. Must name the gateway attached to this table’s VPC. | | `nat-gateway` | Out through a NAT gateway, which translates the traffic to its own address. Must name a NAT gateway in this table’s VPC, and the destination must be `0.0.0.0/0`. | The platform acts on default routes, the ones whose destination is `0.0.0.0/0` or `::/0`. A NAT gateway translates IPv4 only, so a `::/0` route or any narrower destination with a `nat-gateway` target is refused. ## How internet access is decided [#how-internet-access-is-decided] The platform decides internet reachability per VPC and address family. If any route table used by a subnet of the VPC has a default route to the Internet Gateway or a NAT gateway, traffic of that family can leave the VPC. A working connection also needs a public source address. An instance gets one from its own Floating IP, or from a NAT gateway when its subnet’s table routes `0.0.0.0/0` through one. A subnet whose table has no default route gets no working internet access. Its packets can still leave the VPC while another subnet’s table has a default route, but no reply comes back. To stop a subnet’s outbound traffic, use network ACL egress rules or security group egress rules; see [Traffic control](/docs/network/traffic-control). ## Change routes [#change-routes] `update-route-table-routes` replaces the table’s whole route list. Send every route the table should keep, including its local routes. Read the current list with `get-route-table` first. Each `--route` takes `,[,]`: ```sh origin network update-route-table-routes \ --route-table-urn \ --route '10.0.0.0/16,local' \ --route ',local' \ --route '0.0.0.0/0,internet-gateway,' ``` A change takes effect within a few seconds and applies to new connections. A connection that’s already open through a gateway keeps running until it closes or times out, so removing a route doesn’t cut a transfer in progress. ## Associate a subnet with a table [#associate-a-subnet-with-a-table] `associate-route-table` points a subnet at a table, replacing the one it used before. The table must belong to the subnet’s VPC. ```sh origin network associate-route-table --subnet-urn \ --route-table-urn ``` ## What is refused [#what-is-refused] - Deleting a VPC’s main route table. It’s removed only with the VPC. - Deleting a table that a subnet still uses. Associate those subnets with another table first. - A route that names an Internet Gateway of another VPC, or a detached gateway. - A route that names a NAT gateway of another VPC, or one that no longer exists. - Deleting a NAT gateway while any table still routes through it. - Detaching an Internet Gateway while a table other than the main one still routes through it. ## Related [#related] - [Give a private subnet internet access with a NAT gateway](/docs/network/internet-access/nat-gateways) - [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways) - [`update-route-table-routes` reference](/docs/network/reference/cli#update-route-table-routes) - [`associate-route-table` reference](/docs/network/reference/cli#associate-route-table) # origin network commands Every origin network command with its flags: VPCs, subnets, gateways, route tables, Floating IPs, ACLs, security groups and DNS policies. This page lists every `origin network` command. Commands that replace a whole rule or server list make you state the full new list; see [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets). ## create-vpc [#create-vpc] Create a VPC, with its default security group, network ACL, route table and first subnet. ```sh origin network create-vpc [OPTIONS] --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--ipv4-cidr ` | no | IPv4 range of the VPC, in private address space (`10.0.0.0/8`, `172.16.0.0/12` or `192.168.0.0/16`), from `/16` to `/28`. Omitted, a random `/16` from `172.16.0.0/12` that doesn’t collide with your other VPCs is assigned. | ## list-vpcs [#list-vpcs] List the VPCs of a project. ```sh origin network list-vpcs --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## create-subnet [#create-subnet] Create a subnet in a VPC. ```sh origin network create-subnet --vpc-urn --auto-assign-public-ip ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | | `--auto-assign-public-ip ` | yes | Whether instances launched into the subnet automatically get a Floating IP: `true` or `false`. Required, so it reads the same as on [`update-subnet-auto-assign-public-ip`](#update-subnet-auto-assign-public-ip). | ## list-subnets [#list-subnets] List the subnets of a project. ```sh origin network list-subnets --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-network-interface [#get-network-interface] Get a single Network Interface. Interfaces are created via [`create-network-interface`](#create-network-interface) or implicitly during instance launch, and are removed automatically on instance termination or subnet/VPC deletion - use [`delete-network-interface`](#delete-network-interface) to remove a standalone one directly. ```sh origin network get-network-interface --network-interface-urn ``` | Option | Required | Description | | --- | --- | --- | | `--network-interface-urn ` | yes | URN of the Network Interface. | ## delete-network-interface [#delete-network-interface] Delete a standalone Network Interface. Refuses while it’s still attached to something (a Compute instance or an Internet Gateway); detach or terminate whatever’s using it first. Refuses too while a Floating IP is still associated with it - [`disassociate-floating-ip`](#disassociate-floating-ip) first, or the address could never be released afterwards. ```sh origin network delete-network-interface --network-interface-urn ``` | Option | Required | Description | | --- | --- | --- | | `--network-interface-urn ` | yes | URN of the Network Interface. | ## list-network-interfaces [#list-network-interfaces] List Network Interfaces for a project. ```sh origin network list-network-interfaces --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## list-floating-ips [#list-floating-ips] List Floating IPs for a project. ```sh origin network list-floating-ips --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-internet-gateway [#get-internet-gateway] Get a VPC’s Internet Gateway, if it has one attached. ```sh origin network get-internet-gateway --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## attach-internet-gateway [#attach-internet-gateway] Attach an Internet Gateway to a VPC, making its subnets internet-facing. ```sh origin network attach-internet-gateway --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## detach-internet-gateway [#detach-internet-gateway] Detach a VPC’s Internet Gateway, making its subnets private again. ```sh origin network detach-internet-gateway --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## delete-vpc [#delete-vpc] Delete a VPC and everything it owns, then release its claimed CIDR(s) back to the pool. Refuses if any subnet still has an attached network interface, or while any NAT gateway lives in the VPC - delete those with [`delete-nat-gateway`](#delete-nat-gateway) first. ```sh origin network delete-vpc --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## delete-subnet [#delete-subnet] Delete a subnet. Refuses if it still has an attached network interface, or while a NAT gateway lives in it. Never releases the owning VPC’s CIDR capacity - that only happens on [`delete-vpc`](#delete-vpc) ```sh origin network delete-subnet --subnet-urn ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the subnet. | ## get-floating-ip [#get-floating-ip] Get a Floating IP. ```sh origin network get-floating-ip --floating-ip-urn ``` | Option | Required | Description | | --- | --- | --- | | `--floating-ip-urn ` | yes | URN of the Floating IP. | ## allocate-floating-ip [#allocate-floating-ip] Allocate a Floating IP from the platform’s public IPv4 pool. It stays unassociated until [`associate-floating-ip`](#associate-floating-ip). ```sh origin network allocate-floating-ip --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## associate-floating-ip [#associate-floating-ip] Associate a Floating IP with a network interface, enabling static 1:1 NAT for it. Errors if already associated - [`disassociate-floating-ip`](#disassociate-floating-ip) first. ```sh origin network associate-floating-ip --floating-ip-urn --network-interface-urn ``` | Option | Required | Description | | --- | --- | --- | | `--floating-ip-urn ` | yes | URN of the Floating IP. | | `--network-interface-urn ` | yes | URN of the network interface to associate it with. | ## disassociate-floating-ip [#disassociate-floating-ip] Disassociate a Floating IP, removing its NAT rules. Idempotent. ```sh origin network disassociate-floating-ip --floating-ip-urn ``` | Option | Required | Description | | --- | --- | --- | | `--floating-ip-urn ` | yes | URN of the Floating IP. | ## release-floating-ip [#release-floating-ip] Release a Floating IP back to the pool and delete it. Errors if still associated - [`disassociate-floating-ip`](#disassociate-floating-ip) first. ```sh origin network release-floating-ip --floating-ip-urn ``` | Option | Required | Description | | --- | --- | --- | | `--floating-ip-urn ` | yes | URN of the Floating IP. | ## get-vpc [#get-vpc] Get a single VPC. ```sh origin network get-vpc --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## get-subnet [#get-subnet] Get a single Subnet. ```sh origin network get-subnet --subnet-urn ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the subnet. | ## get-security-group [#get-security-group] Get a Security Group and its rules. ```sh origin network get-security-group --security-group-urn ``` | Option | Required | Description | | --- | --- | --- | | `--security-group-urn ` | yes | URN of the Security Group. | ## list-security-groups [#list-security-groups] List every Security Group in a project. ```sh origin network list-security-groups --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## create-security-group [#create-security-group] Create an additional, non-default Security Group in a VPC. Starts with no ingress/egress rules - use [`update-security-group-rules`](#update-security-group-rules) afterwards to add rules. ```sh origin network create-security-group --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## delete-security-group [#delete-security-group] Delete a non-default Security Group. Refuses to delete a VPC’s default Security Group, or one still attached to a Network Interface. ```sh origin network delete-security-group --security-group-urn ``` | Option | Required | Description | | --- | --- | --- | | `--security-group-urn ` | yes | URN of the Security Group. | ## get-acl [#get-acl] Get a Network ACL and its rules. ```sh origin network get-acl --acl-urn ``` | Option | Required | Description | | --- | --- | --- | | `--acl-urn ` | yes | URN of the Network ACL. | ## list-acls [#list-acls] List every Network ACL in a project. ```sh origin network list-acls --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## list-nat-gateways [#list-nat-gateways] List the NAT Gateways in a project. ```sh origin network list-nat-gateways --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## create-nat-gateway [#create-nat-gateway] Create a NAT Gateway so Instances without a Floating IP can reach the internet. It goes in a public Subnet - one whose Route Table has a default route to an Internet Gateway - and uses a Floating IP you have already allocated and not attached to anything. Point a private Subnet’s Route Table at it with [`update-route-table-routes`](#update-route-table-routes) to send that Subnet’s traffic through it. Instances behind it reach the internet as the Gateway’s address and are not reachable from it. The Floating IP stays yours when the Gateway is deleted. ```sh origin network create-nat-gateway --subnet-urn --floating-ip-urn ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the public Subnet. | | `--floating-ip-urn ` | yes | URN of an allocated, unattached Floating IP. | ## delete-nat-gateway [#delete-nat-gateway] Delete a NAT Gateway. Refuses while any Route Table still routes through it. ```sh origin network delete-nat-gateway --nat-gateway-urn ``` | Option | Required | Description | | --- | --- | --- | | `--nat-gateway-urn ` | yes | URN of the NAT Gateway. | ## list-route-tables [#list-route-tables] List the Route Tables in a project. ```sh origin network list-route-tables --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-route-table [#get-route-table] Show one Route Table. ```sh origin network get-route-table --route-table-urn ``` | Option | Required | Description | | --- | --- | --- | | `--route-table-urn ` | yes | URN of the Route Table. | ## create-route-table [#create-route-table] Create an additional Route Table in a VPC. It starts with the VPC’s local routes and no default route, so a Subnet associated with it reaches its own VPC and nothing else - the “private subnet” half of the public/private pattern. Add a default with [`update-route-table-routes`](#update-route-table-routes). ```sh origin network create-route-table --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## update-route-table-routes [#update-route-table-routes] Replace a Route Table’s routes. This is a wholesale replace, not a patch: pass every route the table should have. `--route` is repeatable and takes `,[,]`, where `` is `local`, `internet-gateway` or `nat-gateway` - e.g. `--route '0.0.0.0/0,internet-gateway,'`, `--route '0.0.0.0/0,nat-gateway,'` or `--route '10.0.0.0/16,local'`. Target URNs have the usual form `urn:origin:cloud:network::::`; the CLI help still shows an internal `ffs:` prefix. A `nat-gateway` route carries a subnet’s whole way out, so its destination must be `0.0.0.0/0`: it translates IPv4 only. ```sh origin network update-route-table-routes --route-table-urn --route ``` | Option | Required | Description | | --- | --- | --- | | `--route-table-urn ` | yes | URN of the Route Table. | | `--route ` | yes | Repeatable. `,[,]` | ## delete-route-table [#delete-route-table] Delete a Route Table. Refuses a VPC’s main table, and one a Subnet is still associated with. ```sh origin network delete-route-table --route-table-urn ``` | Option | Required | Description | | --- | --- | --- | | `--route-table-urn ` | yes | URN of the Route Table. | ## associate-route-table [#associate-route-table] Point a Subnet at a Route Table, replacing whichever it used before. ```sh origin network associate-route-table --subnet-urn --route-table-urn ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the Subnet. | | `--route-table-urn ` | yes | URN of the Route Table. | ## create-acl [#create-acl] Create an additional, non-default Network ACL in a VPC. Starts with no rules - use [`update-acl-rules`](#update-acl-rules) to add rules, and [`update-subnet-acl`](#update-subnet-acl) to attach it to a subnet. ```sh origin network create-acl --vpc-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | ## delete-acl [#delete-acl] Delete a non-default Network ACL. Refuses to delete a VPC’s default ACL, or one still assigned to a Subnet. ```sh origin network delete-acl --acl-urn ``` | Option | Required | Description | | --- | --- | --- | | `--acl-urn ` | yes | URN of the Network ACL. | ## update-subnet-acl [#update-subnet-acl] Reassign which Network ACL enforces a subnet’s traffic. Refuses if the ACL belongs to a different VPC than the subnet. ```sh origin network update-subnet-acl --subnet-urn --acl-urn ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the subnet. | | `--acl-urn ` | yes | URN of the Network ACL to assign. | ## update-subnet-auto-assign-public-ip [#update-subnet-auto-assign-public-ip] Change whether instances launched into a subnet automatically get a Floating IP. Applies only to network interfaces created after the change - existing ones keep whatever Floating IP state they already have (use [`associate-floating-ip`](#associate-floating-ip) / [`disassociate-floating-ip`](#disassociate-floating-ip) for those) ```sh origin network update-subnet-auto-assign-public-ip --subnet-urn --auto-assign-public-ip ``` | Option | Required | Description | | --- | --- | --- | | `--subnet-urn ` | yes | URN of the subnet. | | `--auto-assign-public-ip ` | yes | The new value. Required and explicit (`true` / `false`) rather than a bare flag, so that omitting it can never silently mean “disable” [possible values: `true`, `false`]. | ## get-dns-policy [#get-dns-policy] Get a DNS policy. ```sh origin network get-dns-policy --dns-policy-urn ``` | Option | Required | Description | | --- | --- | --- | | `--dns-policy-urn ` | yes | URN of the DNS policy. | ## list-dns-policies [#list-dns-policies] List every DNS relay policy in a project. ```sh origin network list-dns-policies --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## create-dns-policy [#create-dns-policy] Create an additional, non-default DNS policy in a project. It takes the same options as [`update-dns-policy`](#update-dns-policy). ```sh origin network create-dns-policy --project-urn --relay-enabled <--upstream-server |--no-upstream-servers> ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--relay-enabled ` | yes | Whether this policy relays unanswered queries upstream at all. Required and explicit (`true` / `false`) rather than a bare flag, so that it reads the same way as on [`update-dns-policy`](#update-dns-policy), where omitting it could otherwise silently mean “disable” [possible values: `true`, `false`]. | | `--upstream-server ` | one of `--upstream-server`, `--no-upstream-servers` | IPv4/IPv6 address of an upstream DNS server, repeatable. Required non-empty only while `--relay-enabled true` is given. | | `--no-upstream-servers` | one of `--upstream-server`, `--no-upstream-servers` | Start the policy with no upstream servers - only legal alongside `--relay-enabled false`. Exactly one of `--upstream-server` and `--no-upstream-servers` must be given. | ## update-dns-policy [#update-dns-policy] Replace a DNS relay policy’s own settings wholesale - not which policy is default or which VPC(s) it backs. The upstream server list is replaced on every invocation, so its new contents must be stated: `--upstream-server` for a non-empty list, `--no-upstream-servers` for an empty one. ```sh origin network update-dns-policy --dns-policy-urn --relay-enabled <--upstream-server |--no-upstream-servers> ``` | Option | Required | Description | | --- | --- | --- | | `--dns-policy-urn ` | yes | URN of the DNS policy. | | `--relay-enabled ` | yes | Whether this policy relays unanswered queries upstream at all. Required and explicit (`true` / `false`) rather than a bare flag, so that omitting it can never silently mean “disable” on a policy that currently relays [possible values: `true`, `false`]. | | `--upstream-server ` | one of `--upstream-server`, `--no-upstream-servers` | IPv4/IPv6 address of an upstream DNS server, repeatable - the full given set replaces the existing upstream server list. Required non-empty while `--relay-enabled true` is given. | | `--no-upstream-servers` | one of `--upstream-server`, `--no-upstream-servers` | Replace the upstream server list with the empty set - only legal alongside `--relay-enabled false`. Exactly one of `--upstream-server` and `--no-upstream-servers` must be given. | ## set-default-dns-policy [#set-default-dns-policy] Reassign which policy is a project’s default DNS relay policy - does not touch any VPC’s current attachment. ```sh origin network set-default-dns-policy --dns-policy-urn ``` | Option | Required | Description | | --- | --- | --- | | `--dns-policy-urn ` | yes | URN of the DNS policy to make default. | ## delete-dns-policy [#delete-dns-policy] Delete a DNS relay policy. Refuses if it’s the project’s default, or if any VPC is still attached to it. ```sh origin network delete-dns-policy --dns-policy-urn ``` | Option | Required | Description | | --- | --- | --- | | `--dns-policy-urn ` | yes | URN of the DNS policy. | ## attach-dns-policy [#attach-dns-policy] Change which DNS relay policy a VPC relays through. ```sh origin network attach-dns-policy --vpc-urn --dns-policy-urn ``` | Option | Required | Description | | --- | --- | --- | | `--vpc-urn ` | yes | URN of the VPC. | | `--dns-policy-urn ` | yes | URN of the DNS policy to attach - must belong to the VPC’s own project. | ## create-network-interface [#create-network-interface] Create a standalone network interface in a subnet. ```sh origin network create-network-interface [OPTIONS] --project-urn --subnet-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--subnet-urn ` | yes | URN of the subnet. | | `--security-group-urn ` | no | URN of a Security Group to attach. Repeatable. Omitted defaults to the owning VPC’s default Security Group. | ## update-acl-rules [#update-acl-rules] Replace a Network ACL’s full rule list. State the new list with `--rule` (repeatable), or `--no-rules` for the empty one; stating neither is an error rather than a silent wipe. ```sh origin network update-acl-rules --acl-urn <--rule |--no-rules> ``` | Option | Required | Description | | --- | --- | --- | | `--acl-urn ` | yes | URN of the Network ACL. | | `--rule ` | one of `--rule`, `--no-rules` | One ACL rule, repeatable - the full given set replaces the existing rules. Format: `priority=,direction=,protocol=,port=,source=,policy=`. `icmp` covers ICMP and ICMPv6 and takes `port=any` | | `--no-rules` | one of `--rule`, `--no-rules` | Replace the rules with the empty set, leaving the ACL deny-by-default. Required to say this out loud: exactly one of `--rule` and `--no-rules` must be given. | ## update-security-group-rules [#update-security-group-rules] Replace a Security Group’s full ingress and egress rule lists. Both lists are replaced on every invocation, so each one’s new contents must be stated - `--ingress-rule` / `--egress-rule` for a non-empty list, `--no-ingress-rules` / `--no-egress-rules` for an empty one. Stating neither for a list is an error rather than a silent wipe. ```sh origin network update-security-group-rules --security-group-urn <--ingress-rule |--no-ingress-rules> <--egress-rule |--no-egress-rules> ``` | Option | Required | Description | | --- | --- | --- | | `--security-group-urn ` | yes | URN of the Security Group. | | `--ingress-rule ` | one of `--ingress-rule`, `--no-ingress-rules` | One ingress rule, repeatable - the full given set replaces the existing ingress rules. Format: `protocol=,port=,(ip-range=\|security-group-urn=)[,description=]`. `icmp` covers ICMP and ICMPv6 and takes `port=any` | | `--no-ingress-rules` | one of `--ingress-rule`, `--no-ingress-rules` | Replace the ingress rules with the empty set, admitting no inbound traffic. Exactly one of `--ingress-rule` and `--no-ingress-rules` must be given. | | `--egress-rule ` | one of `--egress-rule`, `--no-egress-rules` | One egress rule, repeatable - same format as `--ingress-rule`. The full given set replaces the existing egress rules. | | `--no-egress-rules` | one of `--egress-rule`, `--no-egress-rules` | Replace the egress rules with the empty set, admitting no outbound traffic. Exactly one of `--egress-rule` and `--no-egress-rules` must be given. | # Network reference Where to find every origin network CLI command and every GraphQL query and mutation in the network namespace of the API. Network has two reference surfaces: the `origin network` CLI commands and the `network` namespace of the GraphQL API. Both cover the same resources. For concepts and procedures, start at [What is Origin Cloud Network?](/docs/network). ## CLI commands [#cli-commands] [origin network commands](/docs/network/reference/cli) lists every command with its flags. For options that apply to every command, see [Global options](/docs/platform/reference/cli#global-options). ## GraphQL queries [#graphql-queries] All queries are fields of `network` on the root query type. For how to call the API, see [API access](/docs/platform/access/api). | Query | Returns | | --- | --- | | `vpcs` | Every VPC in a project. | | `vpc` | One VPC by URN. | | `subnets` | Every subnet in a project. | | `subnet` | One subnet by URN. | | `networkInterfaces` | Every network interface in a project. | | `networkInterface` | One network interface by URN. | | `internetGateway` | A VPC’s Internet Gateway, if it has one. | | `routeTables` | Every route table in a project. | | `routeTable` | One route table by URN. | | `natGateways` | Every NAT gateway in a project. | | `floatingIps` | Every Floating IP in a project. | | `floatingIp` | One Floating IP by URN. | | `acls` | Every network ACL in a project. | | `acl` | One network ACL by URN. | | `securityGroups` | Every security group in a project. | | `securityGroup` | One security group by URN. | | `dnsPolicies` | Every DNS policy in a project. | | `dnsPolicy` | One DNS policy by URN. | ## GraphQL mutations [#graphql-mutations] All mutations are fields of `network` on the root mutation type. | Mutation | Does | | --- | --- | | `createVpc` | Creates a VPC with its first subnet, main route table, default ACL and default security group. | | `deleteVpc` | Deletes a VPC and everything it owns. | | `createSubnet` | Adds a subnet to a VPC. | | `deleteSubnet` | Deletes a subnet. | | `updateSubnetAcl` | Assigns a network ACL to a subnet. | | `updateSubnetAutoAssignPublicIp` | Turns automatic Floating IPs for a subnet on or off. | | `createNetworkInterface` | Creates a standalone network interface in a subnet. | | `deleteNetworkInterface` | Deletes a standalone network interface. | | `attachInternetGateway` | Attaches an Internet Gateway to a VPC. | | `detachInternetGateway` | Detaches a VPC’s Internet Gateway. | | `createRouteTable` | Creates an additional route table in a VPC. | | `updateRouteTableRoutes` | Replaces a route table’s routes. | | `associateRouteTable` | Points a subnet at a route table. | | `deleteRouteTable` | Deletes a route table. | | `createNatGateway` | Creates a NAT gateway in a public subnet. | | `deleteNatGateway` | Deletes a NAT gateway. | | `allocateFloatingIp` | Allocates a Floating IP to a project. | | `associateFloatingIp` | Associates a Floating IP with a network interface. | | `disassociateFloatingIp` | Removes a Floating IP’s association. | | `releaseFloatingIp` | Releases a Floating IP. | | `createAcl` | Creates an additional network ACL in a VPC. | | `updateAclRules` | Replaces a network ACL’s rules. | | `deleteAcl` | Deletes a network ACL. | | `createSecurityGroup` | Creates an additional security group, optionally with initial rules. | | `updateSecurityGroupRules` | Replaces a security group’s ingress and egress rules. | | `deleteSecurityGroup` | Deletes a security group. | | `createDnsPolicy` | Creates a DNS policy in a project. | | `updateDnsPolicy` | Replaces a DNS policy’s relaying setting and upstream servers. | | `attachDnsPolicy` | Attaches a DNS policy to a VPC. | | `setDefaultDnsPolicy` | Makes a DNS policy the project’s default. | | `deleteDnsPolicy` | Deletes a DNS policy. | ## Errors and limits [#errors-and-limits] - [Errors](/docs/platform/reference/errors) - [Limits](/docs/platform/reference/limits) # Traffic control Security groups filter each instance's traffic and network ACLs filter traffic crossing a subnet's boundary. Learn where each one applies. Two kinds of rules decide which traffic reaches your instances. Security groups are stateful firewalls on each network interface and apply to every packet the instance sends or receives. Network ACLs are stateless rule lists on each subnet, and apply to every packet that crosses the subnet’s boundary. Use security groups as your main control, and network ACLs as an extra layer between subnets and toward the internet. The following table shows which rules apply on each path. | Traffic | Security groups | Network ACL | | --- | --- | --- | | Between instances in the same subnet | Yes | No, never | | Between subnets of a VPC | Yes | Egress rules of the source subnet and ingress rules of the destination subnet | | From a subnet to the internet | Yes | Egress rules of the subnet | | From the internet to a subnet | Yes | Ingress rules of the subnet | Whether two instances run on the same machine makes no difference, and the rules are the same in a VPC with or without an Internet Gateway. In a VPC without an Internet Gateway, instances in different subnets can’t reach each other at all; see [VPCs and subnets](/docs/network/vpcs). ## Key concepts [#key-concepts] | Concept | Meaning | | --- | --- | | Security group | A stateful set of ingress and egress rules on a network interface. Anything not allowed is denied, and replies to allowed connections pass automatically. See [Security groups](/docs/network/traffic-control/security-groups). | | Network ACL | A stateless, ordered list of allow and deny rules for a subnet. See [Network ACLs](/docs/network/traffic-control/network-acls), including exactly where they’re enforced. | | Whole-set replacement | Rule and server lists are always replaced as a whole, and every command makes you state the complete new state. See [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets). | ## What you can do [#what-you-can-do] - [Change a security group’s rules](/docs/network/traffic-control/security-groups#change-a-security-groups-rules) - [Create and assign a network ACL](/docs/network/traffic-control/network-acls#create-and-assign-a-network-acl) ## Limits and quotas [#limits-and-quotas] See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Internet access](/docs/network/internet-access) - [Network interfaces](/docs/network/vpcs/network-interfaces) - [origin network commands](/docs/network/reference/cli) # Network ACLs Network ACLs are stateless, ordered rule lists for a subnet. Learn how rules are evaluated, which traffic they apply to, and how to create and assign one. A network ACL is a list of allow and deny rules for a subnet, by direction, protocol, port and address range. Every subnet uses exactly one ACL, and the same rules apply to every instance in the subnet regardless of its security groups. ACLs are enforced at each instance’s network interface, so they apply to every packet that crosses the subnet’s boundary, in any VPC, whether or not it has an Internet Gateway. A network ACL doesn’t filter traffic between instances in the same subnet, whether or not they run on the same machine. To control that traffic, use [security groups](/docs/network/traffic-control/security-groups). ## Where ACLs are enforced [#where-acls-are-enforced] An ACL applies to traffic between an instance in its subnet and an address outside that subnet: | Traffic | ACL rules that apply | | --- | --- | | Between two instances in the same subnet | None | | From subnet A to subnet B of the same VPC | Egress rules of A’s ACL, then ingress rules of B’s ACL | | From a subnet to the internet | Egress rules of the subnet’s ACL | | From the internet to a subnet | Ingress rules of the subnet’s ACL | ACLs are stateless, so this applies to reply traffic too. A reply from subnet B to subnet A needs an egress rule in B’s ACL and an ingress rule in A’s ACL. A reply from a subnet to an internet client needs an egress rule in the subnet’s ACL, and the replies an instance receives to its own outbound connections need an ingress rule. Traffic between an instance and the VPC’s DNS resolver or the instance metadata service isn’t filtered by ACLs. ## How rules are evaluated [#how-rules-are-evaluated] Each rule has a priority, a direction, a protocol, a port, an address range and a policy: | Field | Values | | --- | --- | | `priority` | A number from 0 to 65535. Lower numbers are evaluated first. | | `direction` | `ingress` (traffic entering the subnet) or `egress` (traffic leaving it). | | `protocol` | `any`, `tcp`, `udp` or `icmp`. `icmp` means ICMP when `source` is an IPv4 range and ICMPv6 when it is an IPv6 range, all message types. | | `port` | A single port, a range such as `1024-65535`, or `any`. Applies only with `tcp` or `udp`. ICMP has no ports: an `icmp` rule must use `any`, and any other port is refused. | | `source` | For `ingress`, the address range the traffic comes from. For `egress`, the range it goes to. | | `policy` | `accept` or `drop`. | The first rule that matches decides. Traffic that matches no rule is denied. A rule matches one address family, so allowing both IPv4 and IPv6 takes one rule for `0.0.0.0/0` and one for `::/0`. ## The default ACL [#the-default-acl] Every VPC gets a default ACL, and every new subnet uses it. It allows all traffic in both directions and both address families, with four rules at priorities 500 to 530. Edit it, or create more ACLs when subnets need different rules. A VPC’s default ACL can’t be deleted on its own; it goes with the VPC. ## Create and assign a network ACL [#create-and-assign-a-network-acl] `create-acl` adds an ACL with no rules to a VPC. Add rules with `update-acl-rules`, which replaces the whole list. For example, to allow HTTPS in from anywhere and everything out: ```sh origin network update-acl-rules --acl-urn \ --rule 'priority=100,direction=ingress,protocol=tcp,port=443,source=0.0.0.0/0,policy=accept' \ --rule 'priority=200,direction=egress,protocol=any,port=any,source=0.0.0.0/0,policy=accept' ``` Then point a subnet at it. The ACL must belong to the subnet’s VPC, and the change applies to the subnet’s traffic without recreating anything. ```sh origin network update-subnet-acl --subnet-urn --acl-urn ``` To leave an ACL with no rules, say so with `--no-rules`; `update-acl-rules` with neither `--rule` nor `--no-rules` is refused. See [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets). An ACL other than the default can’t be deleted while a subnet still uses it. ## Related [#related] - [Security groups](/docs/network/traffic-control/security-groups) - [Traffic control](/docs/network/traffic-control) - [`update-acl-rules` reference](/docs/network/reference/cli#update-acl-rules) - [`update-subnet-acl` reference](/docs/network/reference/cli#update-subnet-acl) # Rule sets are replaced as a whole ACL rules, security group rules and DNS upstream servers are replaced as a whole. Learn how each command makes you state the full new state, including an empty one. Network ACL rules, security group rules, route table routes and DNS upstream servers are replaced as a whole set. There is no command to add or remove one rule, and no way to say “leave this part as it is”. Each update writes the complete new state, so each command makes you state that state in full and refuses to run if you leave part of it out. ## What each command needs [#what-each-command-needs] | Command | State it in full with | | --- | --- | | `update-acl-rules` | `--rule …` (repeatable) or `--no-rules` | | `update-security-group-rules` | `--ingress-rule …` or `--no-ingress-rules`, and `--egress-rule …` or `--no-egress-rules` | | `create-dns-policy`, `update-dns-policy` | `--upstream-server …` or `--no-upstream-servers`, and `--relay-enabled true` or `false` | | `update-route-table-routes` | `--route …` (repeatable), including the local routes | | `create-subnet`, `update-subnet-auto-assign-public-ip` | `--auto-assign-public-ip true` or `false` | To change one rule, read the current set with the matching `get-` command, then send the whole set with your change. ## The empty set is stated by name [#the-empty-set-is-stated-by-name] An empty set is a legitimate state. An ACL with no rules denies everything, a security group with no egress rules lets nothing out, and a DNS policy that doesn’t relay needs no upstream servers. You ask for it with its flag, never by leaving an argument out: - `update-acl-rules --acl-urn ` on its own is refused. Add `--no-rules` if you mean an ACL with no rules. - `update-security-group-rules` replaces both lists on every call. Giving only `--ingress-rule` is refused, because it would also replace the egress rules. Repeat `--egress-rule` for the rules you keep, or give `--no-egress-rules`. ## Booleans are explicit [#booleans-are-explicit] `--relay-enabled` and `--auto-assign-public-ip` take `true` or `false` rather than being on when present. Leaving one off an update can’t turn a setting off by accident. A create command takes the same flags as its update command. ## Contradictions are refused [#contradictions-are-refused] Giving both forms of the same list, such as `--rule …` together with `--no-rules`, is an error. `--relay-enabled true` with `--no-upstream-servers` is refused too, because a relaying policy needs at least one server. ## Related [#related] - [Security groups](/docs/network/traffic-control/security-groups) - [Network ACLs](/docs/network/traffic-control/network-acls) - [Manage DNS policies](/docs/network/dns/manage-policies) - [Route tables](/docs/network/internet-access/route-tables) # Security groups Security groups are stateful firewalls on each network interface. Learn how rules and group references work, what the default group allows, and how to change rules. A security group is a firewall for a network interface. Its ingress rules say what may reach the instance and its egress rules say what the instance may send, by protocol, port, and a peer: an IP range or another security group in the same VPC. Security groups apply to every packet to or from the interface, including traffic between instances in the same subnet. ## How rules are evaluated [#how-rules-are-evaluated] Security groups are stateful. Once a rule allows a connection, its reply traffic is allowed automatically, without a rule in the other direction. Anything no rule allows is denied. Each rule has: - A protocol: `any`, `tcp`, `udp` or `icmp`. `icmp` means ICMP for an IPv4 peer and ICMPv6 for an IPv6 peer, all message types. - A port: a single port, a range such as `8000-8100`, or `any`. A port only applies with `tcp` or `udp`. ICMP has no ports, so an `icmp` rule must use `any`; a rule with any other port is refused. - A peer: an IP range such as `203.0.113.0/24` or `0.0.0.0/0`, or a security group. An interface can carry several groups. You choose them when you launch the instance; see [Network interfaces](/docs/network/vpcs/network-interfaces). You can’t change an interface’s security groups afterwards. To change what reaches an instance, change the rules of the groups it carries (see [Change a security group’s rules](#change-a-security-groups-rules)), or launch a new instance with other groups. Address resolution (ARP and IPv6 neighbor discovery) always passes, so an interface can always be found by its neighbors. ICMP that belongs to a connection already allowed, such as the reply to the instance’s own ping or a “fragmentation needed” message, passes too; an `icmp` rule is what allows new ICMP, such as a ping from outside. An instance is never reachable without its security groups. Until the rules of every group on its interface are in place, usually within a few seconds of the start, it passes no traffic except address resolution. ## Rules that name a security group [#rules-that-name-a-security-group] A rule whose peer is a security group matches the private addresses of every interface that currently carries that group, on any machine. The match follows membership as you launch and terminate instances. A group with no members matches nothing. Naming a group in its own rules is the usual way to let the members of a cluster talk to each other. A rule can name only a group in the same VPC; naming a group of another VPC is refused. Group references match private addresses only. Traffic that arrives through a Floating IP, including from an instance in the same VPC, carries a public source address and doesn’t match. See [Floating IPs](/docs/network/internet-access/floating-ips). ## Default security group [#default-security-group] Every VPC gets a default security group, which new interfaces carry when you don’t name one. It has: - An ingress rule that allows all traffic from members of the group itself. - Ingress rules that allow SSH (TCP 22), HTTP (TCP 80), HTTPS (TCP 443) and ICMP from anywhere, each over IPv4 (`0.0.0.0/0`) and IPv6 (`::/0`). - Two egress rules that allow all outbound IPv4 and IPv6 traffic. So an instance launched with the default group answers ping and accepts SSH and web traffic from the internet as soon as it has a public address, and instances that share the group can reach each other on any port. Every other port is closed to anything outside the group until you add a rule. SSH is open to everyone because instances accept only key-based logins: every launch takes a key pair, and password logins are refused. To allow SSH from one address range only, replace the two SSH rules as shown below. A VPC created before these rules were part of the default keeps the rules its default group had; add the ones you want with `update-security-group-rules`. ## Change a security group’s rules [#change-a-security-groups-rules] `update-security-group-rules` replaces both rule lists of a group, so you state both every time. For example, to restrict the default group’s SSH to one IPv4 range while keeping HTTP, HTTPS and ping open to everyone, and keep all outbound traffic allowed: ```sh origin network update-security-group-rules \ --security-group-urn \ --ingress-rule 'protocol=tcp,port=22,ip-range=198.51.100.0/24' \ --ingress-rule 'protocol=tcp,port=80,ip-range=0.0.0.0/0' \ --ingress-rule 'protocol=tcp,port=80,ip-range=::/0' \ --ingress-rule 'protocol=tcp,port=443,ip-range=0.0.0.0/0' \ --ingress-rule 'protocol=tcp,port=443,ip-range=::/0' \ --ingress-rule 'protocol=icmp,port=any,ip-range=0.0.0.0/0' \ --ingress-rule 'protocol=icmp,port=any,ip-range=::/0' \ --ingress-rule 'protocol=any,port=any,security-group-urn=' \ --egress-rule 'protocol=any,port=any,ip-range=0.0.0.0/0' \ --egress-rule 'protocol=any,port=any,ip-range=::/0' ``` The example replaces both default SSH rules with one IPv4 rule, so SSH over IPv6 is no longer allowed. Add an SSH rule for an IPv6 range if you need one. Read the current rules with `get-security-group` first, and repeat the ones you want to keep. For the rules about stating lists in full, see [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets). A change applies to every instance whose interface carries the group, usually within a few seconds. You don’t restart the instance. ## Create and delete security groups [#create-and-delete-security-groups] `create-security-group` adds a group to a VPC with no rules, so it denies everything in both directions until you add rules. Use extra groups when different workloads need different rules. The API can seed the rules when it creates the group: the `createSecurityGroup` mutation takes optional `ingressRules` and `egressRules`. Leave them out for an empty group, as the CLI creates. For example, a group that allows HTTPS in from anywhere over IPv4 and all outbound IPv4 traffic: ```graphql mutation { network { createSecurityGroup(input: { vpcUrn: "" ingressRules: [ { protocol: TCP, port: { from: 443 }, peer: { ipRange: "0.0.0.0/0" } } ] egressRules: [ { protocol: ANY, port: {}, peer: { ipRange: "0.0.0.0/0" } } ] }) { urn } } } ``` Omit `from` and `to` in `port` for any port, set only `from` for one port, or both for a range. A VPC’s default security group can’t be deleted on its own; it goes with the VPC. Any other group can’t be deleted while a network interface still carries it. ## Related [#related] - [Network ACLs](/docs/network/traffic-control/network-acls) - [`update-security-group-rules` reference](/docs/network/reference/cli#update-security-group-rules) - [`create-security-group` reference](/docs/network/reference/cli#create-security-group) # Troubleshoot Network Fixes for common Network problems - no internet access, IPv6 errors, refused VPC, subnet and NAT gateway requests, and connections that hang. ## Find your symptom [#find-your-symptom] ## An instance can’t reach the internet [#an-instance-cant-reach-the-internet] Connections from an instance to internet addresses time out, or nothing on the internet can reach the instance. Internet access needs every link of the path to be in place. One of them is missing. Check each item in order: 1. The VPC has an Internet Gateway: `origin network get-internet-gateway --vpc-urn `. See [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). 2. The instance has a way out. Either its network interface has a Floating IP (`list-floating-ips` shows the interface in `networkInterfaceUrn`), or its subnet’s route table has a `0.0.0.0/0` route to a NAT gateway. Without one of these, it has no internet access. See [Floating IPs](/docs/network/internet-access/floating-ips) and [NAT gateways](/docs/network/internet-access/nat-gateways). 3. The subnet’s route table has a `0.0.0.0/0` route to the Internet Gateway or to a NAT gateway. Check with `get-subnet` (its `routeTableUrn`) and `get-route-table`. See [Route tables](/docs/network/internet-access/route-tables). 4. The subnet’s network ACL has egress rules that allow the traffic to the internet, including replies to inbound connections. See [Network ACLs](/docs/network/traffic-control/network-acls). 5. The instance’s security groups allow the traffic. For inbound connections, a group needs an ingress rule for the port and the client’s address range; the default group has them only for SSH, HTTP, HTTPS and ICMP. See [Security groups](/docs/network/traffic-control/security-groups). 6. The instance launched with an automatic public IP actually got one. If no address was available at launch, the instance runs without one. Associate a Floating IP by hand. ## IPv6 connections to the internet fail or hang [#ipv6-connections-to-the-internet-fail-or-hang] An instance trying to reach an internet address over IPv6 either gets an immediate ICMPv6 administratively prohibited error, which many clients report as `Permission denied`, or waits until the connection times out. Instances can’t reach the internet over IPv6. Which of the two you see depends on the VPC’s [IPv6 range](/docs/network/vpcs/addressing#ipv6-addresses). Let the client fall back to IPv4, or configure the guest to prefer IPv4. Don’t retry over IPv6. See [VPC and subnet addressing](/docs/network/vpcs/addressing). ## Instances in different subnets can’t reach each other [#instances-in-different-subnets-cant-reach-each-other] Instances in the same subnet reach each other, but connections to instances in another subnet of the same VPC time out. Traffic between subnets goes through the VPC router, which serves a VPC only while it has an Internet Gateway attached. If the VPC has one, a network ACL or security group may deny the traffic. 1. Attach an Internet Gateway to the VPC if it has none. See [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). 2. Check both subnets’ network ACLs: the source subnet needs an egress rule and the destination subnet an ingress rule, for both the request and the reply. See [Network ACLs](/docs/network/traffic-control/network-acls). 3. Check the security groups of both instances. ## create-vpc without --ipv4-cidr is refused [#create-vpc-without---ipv4-cidr-is-refused] `create-vpc` fails with `no default private IPv4 range is available for another VPC in this organisation; specify an IPv4 CIDR for this VPC explicitly`. The platform picks default ranges from 16 `/16` ranges, and your organization’s VPCs already use them, or the random choice found no free one. Run `create-vpc` again with `--ipv4-cidr` and a private range between `/16` and `/28`. See [VPC and subnet addressing](/docs/network/vpcs/addressing). ## A subnet or VPC delete is refused [#a-subnet-or-vpc-delete-is-refused] `delete-subnet` or `delete-vpc` fails, naming a network interface or a NAT gateway. An attached network interface or a NAT gateway is still in the subnet or VPC. 1. For a network interface, terminate the instance that uses it. See [Terminate an instance](/docs/compute/instances/terminate). 2. For a NAT gateway, remove the routes that name it, then delete it. See [Delete a NAT gateway](/docs/network/internet-access/nat-gateways#delete-a-nat-gateway). 3. Run the delete again. See [Delete a subnet or VPC](/docs/network/vpcs/delete). ## A connection to a Floating IP from inside the VPC hangs [#a-connection-to-a-floating-ip-from-inside-the-vpc-hangs] An instance connects to the Floating IP of another instance, or to its own, and the connection hangs. The same connection from outside the platform works, or the connection works by private address. One of two things: - The server’s security groups don’t allow the caller’s public address. Traffic through a Floating IP carries a public source address, which rules that name a security group don’t match. - The caller is in a different VPC from the Floating IP. A Floating IP is reachable from inside the platform only from its own VPC. Add an ingress rule for the caller’s public address (its own Floating IP, or the Floating IP it calls), or connect by private address within the VPC. From another VPC, connect from outside the platform instead. See [Floating IPs](/docs/network/internet-access/floating-ips). ## create-nat-gateway is refused [#create-nat-gateway-is-refused] `create-nat-gateway` fails. The message names one of these: - `a nat gateway must live in a public subnet`: the subnet’s route table has no default route to an Internet Gateway. - `this floating ip is associated with a network interface`: the Floating IP is in use by an instance. - `this floating ip already backs nat gateway`: each gateway needs its own Floating IP. - [`PAYMENT_METHOD_REQUIRED`](/docs/platform/reference/errors#payment_method_required): the billing account your project is charged to has no verified payment method. See [Add a payment method](/docs/platform/billing/payment-method). - A quota message naming NAT gateways. Create the gateway in a subnet that uses the main route table of a VPC with an Internet Gateway, or add a default route to the Internet Gateway to the subnet’s table. Use a Floating IP that’s allocated and unassociated, or allocate a new one. See [NAT gateways](/docs/network/internet-access/nat-gateways). ## update-acl-rules or update-security-group-rules is refused without contacting the API [#update-acl-rules-or-update-security-group-rules-is-refused-without-contacting-the-api] The CLI exits with `the following required arguments were not provided`, naming `<--rule |--no-rules>`, or `<--egress-rule |--no-egress-rules>` and its ingress counterpart. These commands replace the whole rule list, so they require you to state the new list. Leaving it out would delete every rule. Give every rule you want to keep with `--rule`, `--ingress-rule` or `--egress-rule`. If you do want an empty list, give `--no-rules`, `--no-ingress-rules` or `--no-egress-rules`. See [Rule sets are replaced as a whole](/docs/network/traffic-control/replace-rule-sets). # VPC and subnet addressing How a VPC's IPv4 and IPv6 ranges are chosen, how large its subnets are, which addresses are reserved, and what happens when address space runs out. Every VPC has one private IPv4 range and one IPv6 range. Each subnet gets its own slice of both, and every network interface gets one IPv4 and one IPv6 address from its subnet. The VPC’s IPv4 range is fixed when you create the VPC, and so is the size of every subnet in it. ## The VPC’s IPv4 range [#the-vpcs-ipv4-range] You can choose the IPv4 range with `--ipv4-cidr` when you create the VPC. It must be private address space (`10.0.0.0/8`, `172.16.0.0/12` or `192.168.0.0/16`) and sized between `/16` and `/28`. If you don’t choose one, the platform picks a random `/16` from `172.16.0.0/16` to `172.31.0.0/16` that no other VPC in your organization uses. There are only 16 such ranges, so `create-vpc` without `--ipv4-cidr` can be refused with a message telling you to specify an IPv4 CIDR. Pass a range of your own and the request succeeds. ## Subnet size [#subnet-size] Subnets are eight bits narrower than the VPC, with `/29` as the smallest size. The following table shows some examples. | VPC range | Subnet size | Subnets per VPC | Usable addresses per subnet | | --- | --- | --- | --- | | `/16` | `/24` | 256 | 252 | | `/20` | `/28` | 256 | 12 | | `/21` to `/28` | `/29` | 2 to 256 | 4 | You can’t choose a subnet’s size or resize a subnet. If you need more instances per subnet, create a VPC with a wider range. ## Reserved addresses [#reserved-addresses] Four IPv4 addresses in every subnet aren’t available for instances: - The network address (for example, `10.0.1.0` in `10.0.1.0/24`) - The router address, the first address after the network address (`10.0.1.1`) - The DNS resolver address, the second address after the network address (`10.0.1.2`) - The broadcast address (`10.0.1.255`) Instances use the router address as their default gateway and the DNS resolver address as their name server. The subnet’s `ipv4Router` and `ipv4DnsServers` fields show both. ## IPv6 addresses [#ipv6-addresses] The platform assigns every VPC a `/56` IPv6 range; you can’t choose it. Each subnet gets a `/72` from it, and each network interface gets one address from its subnet. IPv6 works between instances inside the VPC. It doesn’t work between an instance and the internet, in either direction. What an outbound IPv6 connection to an internet address does depends on the VPC’s IPv6 range, the `networkCidr` in the VPC’s networks list: | VPC IPv6 range | Outbound IPv6 to the internet | | --- | --- | | Starts with `fd` (a private range) | Refused immediately with an ICMPv6 “administratively prohibited” error. Clients that fall back to IPv4, such as browsers, curl and package managers, then connect over IPv4 without waiting. | | Any other range | Gets no answer. A client waits for its connection timeout before it falls back to IPv4. | To avoid the wait, configure the guest to prefer IPv4 for internet destinations, for example with a `precedence ::ffff:0:0/96 100` line in `/etc/gai.conf` on Linux. ## When address space runs out [#when-address-space-runs-out] Address space can run out in three places. Each case is refused with a message that names what ran out: - The VPC has no room for another subnet. `create-subnet` is refused. Use a different VPC, or create a new one with a wider IPv4 range. Deleting a subnet doesn’t give its range back to the VPC. - The subnet has no free address. Creating a network interface, and so launching an instance into that subnet, is refused. Use a different subnet, or delete network interfaces you no longer need; their addresses become free again. - The platform has no IPv6 range left for a new VPC. `create-vpc` is refused, because every VPC needs an IPv6 range. A VPC’s address ranges go back to the platform only when you delete the whole VPC. For what happens to a VPC’s IPv6 range after deletion, see [Delete a subnet or VPC](/docs/network/vpcs/delete). ## Related [#related] - [Create a VPC and subnets](/docs/network/vpcs/create) - [Network interfaces](/docs/network/vpcs/network-interfaces) - [Limits](/docs/platform/reference/limits) # Create a VPC and subnets Create a VPC with the CLI, add subnets to it, and choose whether instances launched into each subnet get a public IPv4 address automatically. Create your own VPC when you want to choose its address range or control which subnets reach the internet. A new VPC comes with a first subnet, so you add subnets only when you need more than one. ## Before you begin [#before-you-begin] - The `origin` CLI, signed in. See [CLI access](/docs/platform/access/cli). - The URN of the project to create the VPC in. - If you want your own IPv4 range, a private range between `/16` and `/28`. See [VPC and subnet addressing](/docs/network/vpcs/addressing) for how the range sets the subnet size. Creating VPCs and subnets doesn’t require a payment method. ## Create the VPC [#create-the-vpc] 1. Create the VPC. Pass `--ipv4-cidr` to choose the IPv4 range, or leave it out to get a random `/16` from `172.16.0.0/12`. ```sh origin network create-vpc --project-urn \ --ipv4-cidr 10.0.0.0/16 ``` 1. Note the VPC’s URN from the output, and find its first subnet: ```sh origin network list-subnets --project-urn ``` 1. Verify the VPC with `get-vpc`. Its `ipv4Network` shows the range and the subnet size. ```sh origin network get-vpc --vpc-urn ``` The VPC has no Internet Gateway. To give it internet access, see [Internet access](/docs/network/internet-access). ## Add a subnet [#add-a-subnet] 1. Create the subnet. `--auto-assign-public-ip` is required: `true` gives every instance launched into the subnet a Floating IP automatically, `false` doesn’t. ```sh origin network create-subnet --vpc-urn \ --auto-assign-public-ip false ``` The platform picks the subnet’s ranges from the VPC. If the VPC has no room left, the command is refused; see [When address space runs out](/docs/network/vpcs/addressing#when-address-space-runs-out). 1. Verify the subnet. Its `ipv4Network`, `ipv4Router` and `ipv4DnsServers` show its range, gateway and resolver. ```sh origin network get-subnet --subnet-urn ``` An automatic public IP is only useful if the VPC has an Internet Gateway. For how auto-assigned addresses behave, see [Default VPC](/docs/network/vpcs/default-vpc). ## Change a subnet’s auto-assign setting [#change-a-subnets-auto-assign-setting] 1. Set the new value with `true` or `false`: ```sh origin network update-subnet-auto-assign-public-ip \ --subnet-urn --auto-assign-public-ip true ``` 1. Verify that the subnet’s `autoAssignPublicIp` field shows the new value: ```sh origin network get-subnet --subnet-urn ``` The change applies only to instances launched afterwards. To give a running instance a public address, associate a Floating IP with its interface; see [Floating IPs](/docs/network/internet-access/floating-ips). ## Next steps [#next-steps] - [Launch an instance](/docs/compute/instances/launch) into the subnet with `--subnet-urn` - [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways) ## Related [#related] - [`create-vpc` reference](/docs/network/reference/cli#create-vpc) - [`create-subnet` reference](/docs/network/reference/cli#create-subnet) - [`update-subnet-auto-assign-public-ip` reference](/docs/network/reference/cli#update-subnet-auto-assign-public-ip) # Default VPC The platform creates a default VPC for a project the first time you launch an instance without a subnet. Learn what it contains and how auto-assigned public IPs work. You don’t have to create a VPC before you launch your first instance. If you launch without `--subnet-urn`, the platform uses your project’s default VPC, and creates it the first time a launch needs it. Every later launch without a subnet reuses the same default VPC and its subnet. ## What the default VPC contains [#what-the-default-vpc-contains] The default VPC differs from a VPC you create in two ways: - It has an Internet Gateway attached from the start. - Its subnet has auto-assign public IP turned on, so every instance launched into it gets a Floating IP. Everything else is the same as for any other VPC: a random private /16 IPv4 range, an IPv6 range, a main route table, a default network ACL and a default security group. For the address rules, see [VPC and subnet addressing](/docs/network/vpcs/addressing). The default security group admits SSH, HTTP, HTTPS and ICMP from anywhere, and all traffic from other members of the same group. An instance in the default VPC with a public address answers ping and accepts SSH right after launch; every other port needs an ingress rule. See [Security groups](/docs/network/traffic-control/security-groups). A VPC you create with `create-vpc` never becomes a project’s default VPC. ## Auto-assigned public IPs [#auto-assigned-public-ips] A subnet’s auto-assign public IP setting decides whether instances launched into it get a Floating IP automatically. The default VPC’s subnet has it on; you can turn it on or off for any subnet. See [Create a VPC and subnets](/docs/network/vpcs/create). When the setting is on, the platform allocates a Floating IP and associates it with the instance’s network interface at launch. If that fails for any reason, for example because no public address is available, the launch still succeeds and the instance runs without a public IP. An auto-assigned Floating IP is released when you terminate the instance. You don’t have to release it yourself. To keep a public address across instances, allocate a Floating IP yourself instead; the platform never releases an address you allocated. See [Floating IPs](/docs/network/internet-access/floating-ips). Changing the setting affects only instances launched afterwards. Turning it on doesn’t give a Floating IP to running instances, and turning it off doesn’t take one away. ## When to use your own VPC instead [#when-to-use-your-own-vpc-instead] Create your own VPC when you want private-only instances, your own address range, or more than one subnet. Name its subnet with `--subnet-urn` when you launch. For the launch command, see [Launch an instance](/docs/compute/instances/launch). ## Related [#related] - [Create a VPC and subnets](/docs/network/vpcs/create) - [Internet access](/docs/network/internet-access) # Delete a subnet or VPC Delete a subnet or a whole VPC, clear what blocks the deletion, and learn what is removed with it and what happens to its address ranges. You can delete a single subnet, or a whole VPC with everything it owns. Both are refused while something still uses the network, and the refusal names what is in the way. ## Before you begin [#before-you-begin] - The URN of the subnet or VPC. - Terminate the instances in it, or move your workload elsewhere. See [Terminate an instance](/docs/compute/instances/terminate). - Delete every NAT gateway in it. A NAT gateway holds one of your Floating IPs and is billed until you delete it, so it’s never deleted with its subnet or VPC. See [NAT gateways](/docs/network/internet-access/nat-gateways). ## What a deletion removes [#what-a-deletion-removes] Deleting a subnet removes the subnet and any unattached network interfaces in it. Deleting a VPC removes every subnet in it, its route tables, network ACLs, security groups and Internet Gateway. It doesn’t delete the VPC’s DNS policy, because a policy belongs to the project and can serve other VPCs. Delete the policy separately if you no longer need it; see [Manage DNS policies](/docs/network/dns/manage-policies). ## Delete a subnet [#delete-a-subnet] 1. Delete the subnet: ```sh origin network delete-subnet --subnet-urn ``` If the command is refused, the message names the network interface or NAT gateway that blocks it. Remove that and run the command again. 1. Verify that the subnet no longer appears: ```sh origin network list-subnets --project-urn ``` Deleting a subnet doesn’t return its range to the VPC, even if it was the VPC’s last subnet. A new subnet in the same VPC gets a different range. ## Delete a VPC [#delete-a-vpc] 1. Delete the VPC: ```sh origin network delete-vpc --vpc-urn ``` The refusal names the subnet and network interface, or each NAT gateway, that blocks it. A blocking interface can be in any of the VPC’s subnets. 1. Verify that the VPC no longer appears: ```sh origin network list-vpcs --project-urn ``` ## What happens to the address ranges [#what-happens-to-the-address-ranges] The VPC’s private IPv4 range is free for your next VPC right away. The VPC’s IPv6 range goes back to the platform, which holds it back for one day before assigning it to another VPC. That gives DNS records and allow-lists that still name the old addresses time to expire. ## Other “still in use” refusals [#other-still-in-use-refusals] The same rule applies elsewhere in Network. Each of these is refused, with a message naming the reason, until you remove the dependency: - Deleting a network interface that’s attached, or that a Floating IP is still associated with - Deleting a network ACL that a subnet still uses - Deleting a security group that a network interface still carries - Deleting a route table that a subnet still uses - Deleting a DNS policy that a VPC is still attached to - Releasing a Floating IP that’s still associated ## Related [#related] - [`delete-subnet` reference](/docs/network/reference/cli#delete-subnet) - [`delete-vpc` reference](/docs/network/reference/cli#delete-vpc) - [Troubleshoot Network](/docs/network/troubleshooting) # VPCs and subnets A VPC is an isolated network with its own address space, divided into subnets. Learn what a VPC comes with and how instances connect to it. A VPC (virtual private cloud) is an isolated network for your resources. It has one private IPv4 range and one IPv6 range, and you divide them into subnets. Every instance connects to exactly one subnet through its network interface. Instances in different VPCs can’t reach each other over their private addresses. The following list shows what a VPC contains when you create it: - A first subnet, with network interfaces attached to it - A main route table - A default network ACL - A default security group - An attachment to the project’s default DNS policy A VPC you create has no Internet Gateway. Until you attach one, nothing in the VPC can reach the internet or be reached from it. ## Default VPC and a VPC you create [#default-vpc-and-a-vpc-you-create] Launching an instance without `--subnet-urn` uses the project’s default VPC, which the platform creates on first use. It is internet-facing from the start. A VPC you create is private until you attach an Internet Gateway. | Property | Default VPC | A VPC you create | | --- | --- | --- | | Created | By the platform, at the first launch without a subnet | By you, with `origin network create-vpc` | | Internet Gateway | Attached from the start | None until you attach one | | Public IPv4 for new instances | Assigned automatically (auto-assign public IP is on) | Only if you turn auto-assign on for the subnet, or associate a Floating IP | | Default security group | Admits SSH, HTTP, HTTPS and ICMP from anywhere, and all traffic from members of the group | The same rules | | Address ranges | A private IPv4 range and an IPv6 range | A private IPv4 range and an IPv6 range | | Main route table and default network ACL | Yes | Yes | See [Default VPC](/docs/network/vpcs/default-vpc) and [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). ## Key concepts [#key-concepts] | Concept | Description | | --- | --- | | VPC | An isolated network in one project. Creating it gives you a first subnet, a main route table, a default network ACL that allows all traffic, a default security group, and an attachment to the project’s default DNS policy. | | Subnet | A slice of the VPC’s IPv4 and IPv6 ranges. A VPC can have many subnets. Each subnet uses one route table and one network ACL, and has a setting that decides whether instances launched into it get a public IPv4 address automatically. | | Addressing | The rules for VPC ranges, subnet sizes and reserved addresses, and what happens when address space runs out. See [VPC and subnet addressing](/docs/network/vpcs/addressing). | | Default VPC | The VPC the platform creates for a project the first time you launch an instance without naming a subnet. See [Default VPC](/docs/network/vpcs/default-vpc). | | Network interface | What holds an instance’s private addresses in a subnet and carries its security groups. See [Network interfaces](/docs/network/vpcs/network-interfaces). | Instances in different subnets of one VPC reach each other through the VPC’s router, which serves a VPC only while it has an Internet Gateway attached. In a VPC without an Internet Gateway, only instances in the same subnet can reach each other. To connect instances across subnets, attach an Internet Gateway; see [Attach and detach an Internet Gateway](/docs/network/internet-access/internet-gateways). ## What you can do [#what-you-can-do] - [Create a VPC and subnets](/docs/network/vpcs/create) - [Delete a subnet or VPC](/docs/network/vpcs/delete) ## Limits and quotas [#limits-and-quotas] The number of VPCs per organization and project is limited. See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Internet access](/docs/network/internet-access) - [Traffic control](/docs/network/traffic-control) - [DNS](/docs/network/dns) - [`origin network` commands](/docs/network/reference/cli) # Network interfaces A network interface holds an instance's private IPv4 and IPv6 addresses in a subnet and carries its security groups. Learn how interfaces are created and removed. A network interface holds an instance’s private IPv4 and IPv6 addresses in one subnet. It also carries the security groups that filter the instance’s traffic, and it’s what a Floating IP is associated with. ## Interfaces created by a launch [#interfaces-created-by-a-launch] Launching an instance creates its network interface in the subnet you name, or in the default VPC’s subnet. You choose its security groups at launch with `--security-group-urn`; without it, the interface gets the VPC’s default security group. You can’t change an interface’s security groups afterwards, but you can [change the rules of the groups it carries](/docs/network/traffic-control/security-groups#change-a-security-groups-rules). When you terminate the instance, its interface is deleted with it. It doesn’t remain as an unattached interface. ## Standalone interfaces [#standalone-interfaces] You can also create an interface on its own with `create-network-interface`. It takes an address from the subnet like any other interface. There is no operation to attach a standalone interface to an instance, so it stays unattached until you delete it with [`delete-network-interface`](/docs/network/reference/cli#delete-network-interface). Deleting a subnet or VPC also removes standalone interfaces in it. ## Interface status [#interface-status] An interface’s `status` shows whether it’s in use: | Status | Meaning | | --- | --- | | `AVAILABLE` | Not attached to anything. | | `ATTACHED` | In use. The `attachedToUrn` field names what it’s attached to. | `delete-network-interface` is refused while the interface is `ATTACHED`, and while a Floating IP is still associated with it. Disassociate the Floating IP first. ## Related [#related] - [Security groups](/docs/network/traffic-control/security-groups) - [Floating IPs](/docs/network/internet-access/floating-ips) - [VPC and subnet addressing](/docs/network/vpcs/addressing) - [`create-network-interface` reference](/docs/network/reference/cli#create-network-interface) # What is Origin Cloud Observability? Observability lets you query CPU, network, and disk metrics that the platform collects for your instances, volumes, and network interfaces. Origin Cloud Observability gives you usage metrics for your own resources: how much CPU time an instance consumes, how many bytes a network interface sends and receives, and how many bytes an instance reads from and writes to a volume. The platform collects these metrics for you. You query them through the GraphQL API to graph activity, size instances, or find a busy disk. ## How metrics flow [#how-metrics-flow] Every 30 seconds the platform collects counter values from your compute instances, and through them from their volumes and network interfaces. A metrics query (`RATE` or `INCREASE`) turns those collected values into a series of data points. Every metric is a counter: a running total, such as total CPU seconds or total bytes received, that grows while the instance runs. A raw total is rarely useful, so a query never returns it. Instead, you pick a statistic, and the platform computes it for each period of your time window: - `RATE` returns the average per-second increase over the period, for example bytes per second. - `INCREASE` returns the total increase over the period, for example bytes transferred in the last five minutes. The platform collects a value for each counter every 30 seconds, but only while the instance runs. Volumes and network interfaces are measured through the instance they're attached to, so a volume or interface that isn't attached to a running instance has no data points. ## Features [#features] - **Built-in metrics**: Five metrics cover CPU time, network traffic, and volume reads and writes. See [Metrics reference](/docs/observability/reference/metrics). - **Metric queries**: One query returns a series of data points per metric for one resource over a time window you choose. See [Query metrics](/docs/observability/query-metrics). ## Ways to access Observability [#ways-to-access-observability] - **GraphQL API**: Metrics are available through the `observability` namespace of the API, with the `metrics` query. See [Query metrics](/docs/observability/query-metrics). For authenticating against the API, see [Use the API](/docs/platform/access/api). The origin CLI has no command for metrics. ## What Observability doesn't do [#what-observability-doesnt-do] - Metrics are collected by the platform only. You can't submit your own metrics. - There's no query that lists metric names. The complete list is in the [Metrics reference](/docs/observability/reference/metrics). - Metrics measure your resources from the outside. They don't show memory use, processes, or file systems inside an instance. - There are no alarms or notifications on metric values. ## Pricing [#pricing] Each metrics query you run and each value the platform collects for your resources are billed. For the rates, see Observability prices in the [price list reference](/docs/pricing/reference/price-list-api). ## Related services [#related-services] - [Instances](/docs/compute/instances): the compute instances whose CPU time is measured. - [Volumes](/docs/storage/volumes): the volumes whose reads and writes are measured. - [Network interfaces](/docs/network/vpcs/network-interfaces): the interfaces whose traffic is measured. ## Next steps [#next-steps] - [Query metrics](/docs/observability/query-metrics) - [Observability reference](/docs/observability/reference) # Query metrics Query the CPU, network, or volume metrics of one resource over a time window with the GraphQL API, and choose the period and statistic. Use the `observability.metrics` query to get a series of data points for one compute instance, volume, or network interface. You choose the metrics, the time window, the length of each period, and whether each data point is a per-second rate or a total increase. ## Before you begin [#before-you-begin] - The URN of the project that holds the resource you want metrics for. The steps use it to find the resource’s URN. - Permission `observability.metric.get` on the resource. The built-in Owner and Viewer roles include it. See [Built-in roles](/docs/iam/roles). - An access token for the API. The examples get one from the `origin` CLI with `origin id token`. See [Use the GraphQL API](/docs/platform/access/api). ## Query the metrics [#query-the-metrics] 1. Find the URN of the resource. Each command lists the resources of a project with their `urn` field: ```sh origin compute list-instances --project-urn origin storage list-volumes --project-urn origin network list-network-interfaces --project-urn ``` 1. Pick the metric names for that resource type. An instance has `oc_compute_instance_cpu_seconds_total`; a volume and a network interface each have two metrics. See [Metrics reference](/docs/observability/reference/metrics). 1. Use a `periodSeconds` of at least 60. The platform collects a value every 30 seconds, and each data point needs two collected values inside its period; a shorter period often returns no data points. 1. Keep the total number of data points, across all metrics in the query, at or below 11,000. For example, one metric over 7 days at a 300-second period is 2,017 data points. 1. Make `from` a multiple of the period (for example, a full hour) so data points line up with clock times. 1. Save the request as `metrics-query.json`. This example asks for the CPU use of an instance as a per-second rate, in 5-minute periods, over 15 minutes: ```json { "query": "query Metrics($input: MetricQueryInput!) { observability { metrics(input: $input) { metricName resourceUrn unit dataPoints { timestamp value } } } }", "variables": { "input": { "resourceUrn": "", "metricNames": ["oc_compute_instance_cpu_seconds_total"], "from": "2026-10-03T10:00:00Z", "to": "2026-10-03T10:15:00Z", "periodSeconds": 300, "statistic": "RATE" } } } ``` Formatted, the GraphQL query in the `query` field reads: ```graphql query Metrics($input: MetricQueryInput!) { observability { metrics(input: $input) { metricName resourceUrn unit dataPoints { timestamp value } } } } ``` 1. Send the request: ```sh curl -s https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ --data @metrics-query.json ``` 1. Check the response. It contains one series per metric name you asked for, in the same order. For `RATE` on `oc_compute_instance_cpu_seconds_total`, a value of `0.5` means the instance used half a vCPU on average during that period. Example output (illustrative): ```json { "data": { "observability": { "metrics": [ { "metricName": "oc_compute_instance_cpu_seconds_total", "resourceUrn": "", "unit": "seconds", "dataPoints": [ { "timestamp": "2026-10-03T10:00:00+00:00", "value": 0.12 }, { "timestamp": "2026-10-03T10:05:00+00:00", "value": 0.48 }, { "timestamp": "2026-10-03T10:10:00+00:00", "value": 1.73 }, { "timestamp": "2026-10-03T10:15:00+00:00", "value": 0.51 } ] } ] } } } ``` Each data point covers the period that ends at its timestamp. The unit is the unit of the counter, so a `RATE` of a seconds counter is seconds per second. Both ends of the window are included: data points fall on `from`, every `periodSeconds` after it, and `to`, which is why a 15-minute window at 300 seconds returns four points. The first point, at `from`, covers the period before `from` (here 09:55 to 10:00). To cover only the window itself, set `from` one period later. A series with an empty `dataPoints` list means the platform has no values for that resource and metric in the window. Common reasons are an instance that was stopped, a volume or network interface that wasn’t attached to a running instance, a metric name that belongs to another resource type, or a window older than the 90 days the platform keeps metrics. Each successful query is billed as one request, however many metrics or data points it returns. A rejected query isn’t billed. See [`observability_api_request`](/docs/pricing/reference/price-list-api#observability_api_request). If the query returns an error, look up its `extensions.code` in [Errors](/docs/observability/reference/metrics#errors). ## Related [#related] - [Metrics reference](/docs/observability/reference/metrics) – every metric, argument, limit, and error. - [What is Origin Cloud Observability?](/docs/observability) – how counters, `RATE`, and `INCREASE` work. - [Use the GraphQL API](/docs/platform/access/api) – authenticating against the GraphQL API. # Observability reference Reference pages for Observability, listing every metric with its unit and meaning, the metrics query arguments, limits, and errors. The reference pages list everything Observability exposes, so you can look up an exact name, argument, or limit. For how metrics work, see [What is Origin Cloud Observability?](/docs/observability). ## Pages [#pages] | Page | What it lists | | --- | --- | | [Metrics](/docs/observability/reference/metrics) | Every metric with its resource type, unit, and what `RATE` and `INCREASE` mean for it, plus the `observability.metrics` query arguments, response fields, limits, and errors. See [Metrics reference](/docs/observability/reference/metrics). | ## Related references [#related-references] - [Errors](/docs/platform/reference/errors) – every error code the API returns. - [Price list API](/docs/pricing/reference/price-list-api) – the rates for metric queries and collected values. # Metrics reference Every metric Observability provides, with resource type, unit, and meaning, plus the metrics query arguments, response fields, limits, and errors. The platform provides the five metrics below, listed by resource type. Every metric is a counter that the platform reads every 30 seconds while the instance runs. To query them, see [Query metrics](/docs/observability/query-metrics); for how counters and statistics work, see [What is Origin Cloud Observability?](/docs/observability). All counters start again from zero when an instance is stopped and started. `RATE` and `INCREASE` account for such a restart, so a data point never turns negative. `INCREASE` is extrapolated to the full period, so it can be a fractional number even for a byte counter. | Metric | Resource type | Unit | | --- | --- | --- | | [`oc_compute_instance_cpu_seconds_total`](#oc_compute_instance_cpu_seconds_total) | Compute instance | `seconds` | | [`oc_network_interface_receive_bytes_total`](#oc_network_interface_receive_bytes_total) | Network interface | `bytes` | | [`oc_network_interface_transmit_bytes_total`](#oc_network_interface_transmit_bytes_total) | Network interface | `bytes` | | [`oc_volume_read_bytes_total`](#oc_volume_read_bytes_total) | Volume | `bytes` | | [`oc_volume_write_bytes_total`](#oc_volume_write_bytes_total) | Volume | `bytes` | ## oc_compute_instance_cpu_seconds_total [#oc_compute_instance_cpu_seconds_total] | Property | Value | | --- | --- | | Resource type | Compute instance | | Unit | `seconds` | | Counts | The total CPU time the instance has consumed, summed over all its vCPUs. | | `RATE` | The average number of busy vCPUs during the period, in CPU seconds per second. `1.0` means one vCPU fully busy; the maximum is the instance type’s vCPU count. | | `INCREASE` | The CPU seconds the instance consumed during the period. | ## oc_network_interface_receive_bytes_total [#oc_network_interface_receive_bytes_total] | Property | Value | | --- | --- | | Resource type | Network interface | | Unit | `bytes` | | Counts | The total bytes the instance has received on the network interface. | | `RATE` | The average inbound throughput during the period, in bytes per second. Multiply by 8 for bits per second. | | `INCREASE` | The bytes received during the period. | ## oc_network_interface_transmit_bytes_total [#oc_network_interface_transmit_bytes_total] | Property | Value | | --- | --- | | Resource type | Network interface | | Unit | `bytes` | | Counts | The total bytes the instance has sent on the network interface. | | `RATE` | The average outbound throughput during the period, in bytes per second. Multiply by 8 for bits per second. | | `INCREASE` | The bytes sent during the period. | ## oc_volume_read_bytes_total [#oc_volume_read_bytes_total] | Property | Value | | --- | --- | | Resource type | Volume | | Unit | `bytes` | | Counts | The total bytes the instance has read from the volume while attached. | | `RATE` | The average read throughput during the period, in bytes per second. | | `INCREASE` | The bytes read during the period. | ## oc_volume_write_bytes_total [#oc_volume_write_bytes_total] | Property | Value | | --- | --- | | Resource type | Volume | | Unit | `bytes` | | Counts | The total bytes the instance has written to the volume while attached. | | `RATE` | The average write throughput during the period, in bytes per second. | | `INCREASE` | The bytes written during the period. | ## Query arguments [#query-arguments] The `observability.metrics` query takes one `input` argument of type `MetricQueryInput` and returns one series per metric name: ```graphql query Metrics($input: MetricQueryInput!) { observability { metrics(input: $input) { metricName resourceUrn unit dataPoints { timestamp value } } } } ``` The fields of `MetricQueryInput`: | Field | Type | Required | Description | | --- | --- | --- | --- | | `resourceUrn` | `Urn` | yes | URN of one compute instance, volume, or network interface. | | `metricNames` | `[String!]` | yes | One or more metric names from this page. Each name returns one series, in the order given. | | `from` | `DateTime` | yes | Start of the time window, as an RFC 3339 timestamp. The first data point is at `from`. | | `to` | `DateTime` | yes | End of the time window, as an RFC 3339 timestamp. Must not be earlier than `from`. | | `periodSeconds` | `Int` | yes | Length of each period and spacing of the data points, in seconds. Values below 1 count as 1. There’s no maximum. Use at least 60, because each data point needs two values collected 30 seconds apart. | | `statistic` | `MetricStatisticInput` | yes | `RATE` (average per-second increase over the period) or `INCREASE` (total increase over the period). | A metric name that exists but belongs to another resource type returns a series without data points. ## Response fields [#response-fields] The query returns a list of `MetricSeries`, one per requested metric name. | Field | Type | Description | | --- | --- | --- | | `metricName` | `String` | The metric name, as requested. | | `resourceUrn` | `Urn` | The resource the series belongs to. | | `unit` | `String` | Unit of the underlying counter: `seconds` or `bytes`. A `RATE` value is this unit per second. | | `dataPoints` | `[MetricDataPoint!]` | The data points in time order. Empty when the platform has no values for the window. | | `dataPoints.timestamp` | `DateTime` | End of the period the data point covers. | | `dataPoints.value` | `Float` | The `RATE` or `INCREASE` for that period. | ## Limits [#limits] | Limit | Value | | --- | --- | | Data points per query | 11,000, summed over all metrics in the query. Each metric contributes `(to - from) / periodSeconds + 1` data points. | | Queries per minute | 60 per organization. Every admitted query counts, including one that later fails for an unknown metric name. | | Concurrent queries | 4 per organization. | | Query duration | 30 seconds. A query that runs longer is stopped and returns `SERVICE_UNAVAILABLE`. | | Data retention | 90 days. Older periods return no data points. | | Collection interval | 30 seconds, while the instance runs. | ## Errors [#errors] Errors carry their code in `extensions.code`. For the general meaning of each code, see [Error codes](/docs/platform/reference/errors). | Code | Cause | What to do | | --- | --- | --- | | `BAD_REQUEST` | A name in `metricNames` isn’t one of the metrics on this page (message: `metric is not in the catalog`), or `resourceUrn` isn’t a compute instance, volume, or network interface. | Correct the metric name or the URN. | | `FORBIDDEN` | You don’t have `observability.metric.get` on the resource. | Ask for a role that includes it, such as Viewer. See [Built-in roles](/docs/iam/roles). | | `CONFLICT` | The query exceeds the data point limit, the per-minute limit, or the concurrency limit. All three return the message `metric query rate limit exceeded; please retry later`. | Check that the query has at most 11,000 data points. If it does, wait a few seconds and retry. | | `SERVICE_UNAVAILABLE` | The query didn’t finish within 30 seconds, or metrics are temporarily unavailable. | Retry. If it keeps timing out, query a shorter window or fewer metrics. | A query that fails isn’t billed. # Use the GraphQL API Call the Origin Cloud GraphQL API with a bearer token, find operations by namespace, read resource URNs, and handle typed enums and errors. The GraphQL API is the complete interface to Origin Cloud: the console and the `origin` CLI use it too. Call it directly for automation, integrations, and operations the CLI doesn’t cover. ## Before you begin [#before-you-begin] - A user account, with the `origin` CLI installed and logged in, or a service account with its client ID and secret. See [Use the CLI](/docs/platform/access/cli) and [Service accounts](/docs/iam/service-accounts). - An HTTP client, such as `curl`, or a GraphQL client library. ## Endpoint [#endpoint] Every request goes to one endpoint: ```text https://api.origincloud.eu/graphql ``` Send queries and mutations as an HTTP `POST` with a JSON body that holds `query` and, optionally, `variables`. The API supports GraphQL introspection, so code generators and IDE plugins can read the schema from the endpoint with a valid token. ## Authenticate [#authenticate] Every request carries an access token as a bearer token in the `Authorization` header: ```text Authorization: Bearer ``` A request without a token, or with an expired or invalid one, fails with the error code `UNAUTHORIZED`. Get a token in one of two ways: - As yourself: log in with the CLI, then print the token with `origin id token --raw`. The CLI renews it when it expires. See [Use the CLI](/docs/platform/access/cli). - As a service account: request a token with the OAuth 2.0 client credentials grant, using the service account’s client ID and secret. See [Service accounts](/docs/iam/service-accounts). Access tokens are short-lived. When a request fails with `UNAUTHORIZED`, get a new token and send the request again. ## Send a request [#send-a-request] 1. Write the query. This one lists the organizations you can access: ```graphql query { admin { organisations { orgId name status } } } ``` 1. Send it with your token: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"query":"{ admin { organisations { orgId name status } } }"}' ``` 1. Verify the response. A successful response has a `data` object and no `errors` array. Example output (illustrative): ```json { "data": { "admin": { "organisations": [ { "orgId": "0a1b2c3d4e5f", "name": "Example GmbH", "status": "ACTIVE" } ] } } } ``` Pass values through variables rather than pasting them into the query text. That avoids quoting problems: ```json { "query": "query($org: OrgId!) { admin { organisation(orgId: $org) { name status } } }", "variables": { "org": "0a1b2c3d4e5f" } } ``` ## Namespaces [#namespaces] Operations are grouped by service. Every query and mutation sits under one of these top-level fields: | Namespace | Queries | Mutations | Covers | | --- | --- | --- | --- | | `admin` | yes | yes | Organizations, projects, billing accounts, quotas, usage and cost, support cases | | `iam` | yes | yes | Members, invites, roles, permissions, service accounts, audit log | | `compute` | yes | yes | Instances, instance types, images, image families, key pairs | | `pvs` | yes | yes | Volumes, snapshots, storage classes | | `network` | yes | yes | VPCs, subnets, network interfaces, gateways, Floating IPs, route tables, security groups, network ACLs, DNS | | `observability` | yes | no | Metrics | For example, launching an instance is `mutation { compute { launchInstance(...) { ... } } }`. ## Resource URNs [#resource-urns] Every resource has a URN, a globally unique identifier returned in its `urn` field. Compute, storage and network operations take URNs as input, such as `projectUrn`, `instanceUrn` or `subnetUrn`. Organization and IAM operations take plain IDs, such as `orgId` and `projectId`. A URN has eight colon-separated parts: ```text urn:origin:cloud::::: ``` | Part | Meaning | | --- | --- | | `urn:origin:cloud` | A fixed prefix. | | `` | The service that owns the resource: `admin`, `iam`, `compute`, `pvs`, `network` or `observability`. | | `` | The region the resource lives in, such as `eu-central1`. Empty for resources that aren’t bound to a region. | | `` and `` | The organization and project that own the resource. Empty where they don’t apply. | | `` | The resource’s own ID within the service. | Examples: | Resource | URN | | --- | --- | | Organization | `urn:origin:cloud:admin::::0a1b2c3d4e5f` | | Project | `urn:origin:cloud:admin::0a1b2c3d4e5f::demo-48291037561` | | Instance | `urn:origin:cloud:compute:eu-central1:0a1b2c3d4e5f:demo-48291037561:i-79PVin5MmNc` | | Built-in role | `urn:origin:cloud:iam::::tc/role/roles/viewer` | Copy a URN from the `urn` field of a response rather than assembling it yourself. The one URN you often need without having it at hand is a project’s: it’s `urn:origin:cloud:admin::::`. The API returns it as the project’s `urn` field, and `origin admin create-project` prints it, but `origin admin get-project` and `list-projects` don’t. ## Typed enums [#typed-enums] Statuses and other closed sets of values are GraphQL enums, not free text. Examples are an organization’s `status` (`PENDING_REVIEW`, `ACTIVE`, `REJECTED`), a billing account’s `paymentMethodStatus`, and an instance’s `status`. - Generate your client types from the schema. A typed client lists every value the schema defines, and fails to compile when a value is added that your code doesn’t handle. - Compare against the enum, not against strings copied from a response. - Handle a value your code doesn’t recognize explicitly, for example by surfacing it, rather than mapping it to a default. ## Lists and pages [#lists-and-pages] Most list queries return a plain list. A few queries that can return many entries, such as the audit log and support cases, return a page instead: the entries plus `total`, `hasMore`, `offset` and `limit`. Read the next page by adding `limit` to `offset`, while `hasMore` is `true`. For page size limits, see [Limits](/docs/platform/reference/limits). ## Errors [#errors] A failed operation returns an `errors` array. Each error has a `message` and, in `extensions`, a stable `code`, a `retryable` flag and a `correlationId`: ```json { "errors": [{ "message": "invalid input on field sizeInGib: must be at least 1", "extensions": { "code": "BAD_REQUEST", "retryable": false, "correlationId": "4bf92f3577b34da6a3ce929d0e0e4736" } }] } ``` Branch on `code`, never on the message text: codes are stable, messages can change. For every code and what to do about it, see [Error codes](/docs/platform/reference/errors). ## Related [#related] - [Use the CLI](/docs/platform/access/cli) - [Error codes](/docs/platform/reference/errors) - [Service accounts](/docs/iam/service-accounts) # Use the CLI Install the origin CLI, log in through your browser or with a device code, manage your session and profile, and read the CLI's JSON output and exit codes. The `origin` CLI lets you manage Origin Cloud from a terminal. Install it, log in once, and every command runs as you until your session expires. ## Before you begin [#before-you-begin] - An Origin Cloud user account. You create one at [console.origincloud.eu](https://console.origincloud.eu); see [Create your account](/docs/platform/getting-started#step-0-create-your-account). - A Linux or macOS machine with an x86-64 or ARM64 processor. The CLI isn’t built for Windows. On Windows, you can run the Linux build of the CLI under WSL (Windows Subsystem for Linux). Install it inside your WSL distribution with the install script below. ## Install the CLI [#install-the-cli] The CLI is published at packages.origincloud.eu as one binary per platform, with a `SHA256SUMS` file and a GPG signature over it. | Binary | Platform | | --- | --- | | `origin-linux-amd64` | Linux, x86-64 | | `origin-linux-arm64` | Linux, ARM64 | | `origin-darwin-arm64` | macOS, Apple silicon | | `origin-darwin-amd64` | macOS, Intel | The Linux builds are statically linked and run on any distribution. ### Install with the install script [#install-with-the-install-script] 1. Run the install script. It picks the binary for your machine, verifies it against `SHA256SUMS`, and installs it to `~/.local/bin`: ```sh curl -fsSL https://packages.origincloud.eu/install.sh | sh ``` The script installs nothing if the checksum doesn’t match, or if your machine has neither `sha256sum` nor `shasum` to check it with. 1. If the script reports that `~/.local/bin` isn’t on your `PATH`, add it: ```sh export PATH="$HOME/.local/bin:$PATH" ``` 1. Verify the installation: ```sh origin --version ``` The script reads these environment variables: | Variable | Default | Effect | | --- | --- | --- | | `ORIGIN_VERSION` | The latest stable version | Install a specific version, for example `v1.9.15`. | | `ORIGIN_INSTALL_DIR` | `~/.local/bin` | Install the binary into this directory. | | `ORIGIN_BASE_URL` | `https://packages.origincloud.eu` | Download from a mirror with the same layout. The checksum is still verified. | For example, to install a specific version: ```sh curl -fsSL https://packages.origincloud.eu/install.sh | ORIGIN_VERSION=v1.9.15 sh ``` ### Install manually [#install-manually] Each version lives under `https://packages.origincloud.eu/cli//`, and `https://packages.origincloud.eu/cli/latest` names the latest stable version. 1. Download the binary for your platform, the checksum file and its signature. For Linux on x86-64: ```sh version="$(curl -fsSL https://packages.origincloud.eu/cli/latest)" base="https://packages.origincloud.eu/cli/${version}" curl -fsSLO "$base/origin-linux-amd64" curl -fsSLO "$base/SHA256SUMS" curl -fsSLO "$base/SHA256SUMS.asc" ``` 1. Optional: verify the signature on `SHA256SUMS` with the Origin Cloud release key: ```sh curl -fsSL https://packages.origincloud.eu/origincloud-release.asc | gpg --import gpg --verify SHA256SUMS.asc SHA256SUMS ``` `gpg` reports `Good signature from Origin Cloud Release `. Check that the key’s fingerprint is exactly: ```text FEE6 FD74 A88C 5DB8 959F 5A1B 0BE6 AF84 2E0B 034A ``` A different fingerprint means the key didn’t come from Origin Cloud. Don’t install the binary. 1. Verify the binary against the checksum file. On macOS, use `shasum -a 256 --check` instead of `sha256sum --check`. ```sh sha256sum --check --ignore-missing SHA256SUMS ``` 1. Make the binary executable and put it on your `PATH`: ```sh chmod +x origin-linux-amd64 mkdir -p ~/.local/bin mv origin-linux-amd64 ~/.local/bin/origin ``` 1. Verify the installation: ```sh origin --version ``` Released versions never change: the files under a version’s directory are the same every time you download them. ## Log in [#log-in] `origin id login` opens the Origin Cloud login page in your browser and waits for you to log in there. The CLI never sees your password. Whatever the login page offers works, including a second factor. 1. Run the login command: ```sh origin id login ``` If no browser opens, the CLI prints the address to open yourself. 1. Log in on the page that opens. The CLI waits up to five minutes, then stops with an error. 1. Verify that you’re logged in. The CLI prints who you are when the login finishes, and this command shows your user: ```sh origin iam current-user ``` ### Log in without a browser [#log-in-without-a-browser] On a machine without a browser, such as a server you reached over SSH, use a device code instead. 1. Run the login command with `--device`: ```sh origin id login --device ``` The CLI prints an address, a short code, and how many minutes the code stays valid. 1. Open the address on any other device, such as your laptop or phone. Check that the page shows the same code, then log in and approve the request. 1. The CLI finishes on its own once you approve. It fails if you deny the request or the code expires first. ## How sessions work [#how-sessions-work] A login stores a session for your local user account. The CLI renews the session’s access token automatically whenever it has expired. When the session itself expires, commands fail with `authentication: not authenticated`, and you run `origin id login` again. The session is stored in `~/.local/share/origincloud/`, or under `$XDG_DATA_HOME/origincloud/` if you set that variable. Treat the directory like a password: anyone who can read it can act as you until the session expires. There’s no logout command. To end the session on a machine, delete the session directory: ```sh rm -rf "${XDG_DATA_HOME:-$HOME/.local/share}/origincloud" ``` The next command then fails as unauthenticated until you run `origin id login` again. For scripts and CI jobs, which can’t log in interactively, use a service account instead. See [Service accounts](/docs/iam/service-accounts). ## Use your access token outside the CLI [#use-your-access-token-outside-the-cli] `origin id token` prints the current access token, renewing it first if it has expired. Without a valid session, it fails with `unauthenticated`. Use it to call the GraphQL API with your own tools. | Command | Prints | | --- | --- | | `origin id token` | `{"token": ""}` | | `origin id token --raw` | The bare token | | `origin id token --as-header` | `{"Authorization": "Bearer "}` | | `origin id token --as-header --raw` | `Authorization: Bearer ` | For example, to send an API request with `curl`: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ -d '{"query":"{ admin { organisations { orgId name status } } }"}' ``` ## Set profile values [#set-profile-values] The profile holds local defaults for the CLI. `origin config profile` shows it, and `origin config profile-set ` changes one value. | Key | Effect | | --- | --- | | `default-username` | Pre-fills the username on the browser login page. You can still change it there. | | `output-format` | The output format. `json` is the only value. | For example: ```sh origin config profile-set default-username jane@example.com ``` The profile is stored in `~/.config/origincloud/`, or under `$XDG_CONFIG_HOME/origincloud/` if you set that variable. ## Read the output [#read-the-output] Every command prints JSON on standard output. Login prompts and messages go to standard error, so you can pipe the output into a tool such as `jq`. - On success, a command exits with `0` and prints the data the API returned. - On failure, it exits with `1` and prints a failure envelope. The `description` carries the API’s message, its error code in parentheses and the correlation id: ```json { "code": "failure", "description": "invalid input on field quota: organisation quota exceeded: ... (BAD_REQUEST) [correlation: 4bf92f3577b34da6a3ce929d0e0e4736]" } ``` The `code` in the envelope is always `failure`. For what the API error code means, see [Error codes](/docs/platform/reference/errors). ## Global options [#global-options] These options go before the command group, for example `origin --api compute list-instances ...`. | Option | Effect | | --- | --- | | `-a`, `--api ` | Sends requests to a different GraphQL endpoint. The default is `https://api.origincloud.eu/graphql`. Login always uses the Origin Cloud login page. | | `-c`, `--config ` | Accepted, but doesn’t change which profile the CLI reads. | | `-d`, `--debug` | Accepted, but doesn’t change the output. | | `-V`, `--version` | Prints the CLI version. `origin version` prints it as JSON. | | `-h`, `--help` | Prints help for the CLI, a command group or a command. | For every command and its options, see the CLI reference of each guide, starting with [Platform CLI commands](/docs/platform/reference/cli). ## Related [#related] - [Use the GraphQL API](/docs/platform/access/api) - [Platform CLI commands](/docs/platform/reference/cli) - [`origin compute` commands](/docs/compute/reference/cli) - [`origin storage` commands](/docs/storage/reference/cli) - [`origin network` commands](/docs/network/reference/cli) - [`origin iam` commands](/docs/iam/reference/cli) # Ways to access Origin Cloud Reach Origin Cloud through the console, the origin CLI or the GraphQL API. All three act as a signed-in user or service account with the same permissions. You work with Origin Cloud through the console, the `origin` CLI or the GraphQL API. All three talk to the same API and act as you, so they see the same organizations and are bound by the same roles. A change you make in one shows up in the others. The following list shows how a person and an automated job reach the GraphQL API, and with which credential. - **Person:** signs in on the login page, through the console or the `origin` CLI, which get an access token for the GraphQL API. - **Automated job:** uses client credentials to get an access token for the GraphQL API. ## Key concepts [#key-concepts] | Concept | What it is | | --- | --- | | Login page | Where people authenticate, with whatever sign-in methods your account has, including a second factor. Neither the console nor the CLI sees your password. See [Use the CLI](/docs/platform/access/cli). | | Access token | A short-lived bearer token that every API request carries in its `Authorization` header. The CLI gets and renews one for you. See [Use the GraphQL API](/docs/platform/access/api). | | Service account | A credential for automation, such as CI jobs and scripts, that authenticates as itself rather than as a person. See [Service accounts](/docs/iam/service-accounts). | | Resource URN | The identifier the API and the CLI use for every resource. See [Use the GraphQL API](/docs/platform/access/api#resource-urns). | ## Compare the access methods [#compare-the-access-methods] | Method | Best for | Authenticates as | | --- | --- | --- | | Console | Working in a browser | A person | | `origin` CLI | Interactive work in a terminal and simple scripts | A person | | GraphQL API | Automation, integrations, and anything the CLI doesn’t cover | A person or a service account | The CLI covers organizations, projects, compute, storage, network and IAM. Some operations exist only in the API, among them billing accounts and payment methods, quotas, metrics and the audit log. ## What you can do [#what-you-can-do] - [Install and use the CLI](/docs/platform/access/cli) - [Call the GraphQL API](/docs/platform/access/api) - [Create a service account for automation](/docs/iam/service-accounts) ## Related [#related] - [Platform CLI commands](/docs/platform/reference/cli) - [Error codes](/docs/platform/reference/errors) # Billing access Billing is kept apart from the Owner role. Learn which billing roles reach a billing account, who holds one from the start, and what an Owner can do without one. Billing is deliberately separate from `roles/owner`. An Owner runs the organization’s infrastructure, but can’t view, create or change a billing account. That takes one of three billing roles, which keeps the people who spend money and the people who manage payment apart. The following table shows which roles reach a billing account, and what an Owner can do without one. | Role | Reaches the billing account with | | --- | --- | | `roles/billing/administrator` | Full access | | `roles/billing/user` | All but delete | | `roles/billing/viewer` | Read | | `roles/owner` | No access to the billing account; it can switch which billing account a project is charged to | ## Billing roles [#billing-roles] | Role | Allows | | --- | --- | | `roles/billing/administrator` | View, list, create, update and delete billing accounts. This includes billing details, payment methods and invoices. | | `roles/billing/user` | Everything the administrator can do, except delete a billing account. | | `roles/billing/viewer` | View and list billing accounts, including their invoices. | Assign billing roles organization-wide, with no project: they govern billing accounts, which belong to the organization rather than to a project. A billing role assigned to a single project isn’t refused, but it isn’t supported and doesn’t give the access you’d expect. To assign a role, see [Assign and revoke roles](/docs/iam/assign-roles). For example, to make someone a billing user: ```sh origin iam assign-role --org-id \ --principal user: \ --role-urn urn:origin:cloud:iam::::tc/role/roles/billing/user ``` ## Who holds a billing role from the start [#who-holds-a-billing-role-from-the-start] Whoever creates an organization gets `roles/billing/administrator` on it, together with `roles/owner`. So the person who signs up can add a payment method right away. Nobody else gets a billing role implicitly. A member you invite holds only the roles you assign, so an Owner you add has no billing access until you grant a billing role as well. Only someone who holds the billing permissions can hand them out: you can assign or revoke a billing role only if you hold every permission it grants, so in practice `roles/billing/administrator`. An Owner without a billing role can’t give one to anyone, including itself. See [Who can assign a role](/docs/iam/access-model#who-can-assign-a-role). ## What the Owner role covers [#what-the-owner-role-covers] Without a billing role, an Owner can still: - Switch which billing account a project is charged to. See [Manage projects](/docs/platform/organizations/projects#change-a-projects-billing-account). - Set, clear and read the organization’s spend limit. - Read usage and cost reports. - Read and set quota budgets on projects. An Owner can’t read a billing account’s details, payment method or invoices, and can’t add a payment method. ## Related [#related] - [Add a payment method](/docs/platform/billing/payment-method) - [Built-in roles](/docs/iam/roles) - [Assign and revoke roles](/docs/iam/assign-roles) # Billing Billing accounts hold your billing details and payment method, and every project is charged to one. Learn how billing accounts, payment methods, invoices and spend limits fit together. Your organization pays for what its projects use through billing accounts. A billing account holds the details invoices are issued to and, for card payment, a verified payment method. Every project is charged to exactly one billing account, and one billing account can pay for many projects. The following list shows how projects, billing accounts and invoices relate. - Each **project** is charged to one **billing account**; several projects can be charged to the same one. - A **billing account** holds the **billing details** and the **payment method**, and receives the **invoices**. ## Key concepts [#key-concepts] | Concept | What it is | | --- | --- | | Billing account | What projects are charged to. Every organization starts with one, named `default`, and every new project is linked to it. You can create more and switch a project to another one. See [Manage projects](/docs/platform/organizations/projects). | | Billing details | The postal address, invoice email, contact person and VAT identification number that invoices are issued to. See [Billing details](#billing-details). | | Payment method | A card on file with the payment provider. Creating billable resources needs a verified payment method on the project’s billing account, unless billing is arranged with Origin Cloud directly. See [Add a payment method](/docs/platform/billing/payment-method). | | Billing roles | Access to billing accounts comes from dedicated roles, not from the Owner role. See [Billing access](/docs/platform/billing/billing-access). | | Invoices | Issued per billing account and billing period, and emailed to the invoice email address with a usage statement attached. The `invoices` field of a billing account lists them, with a path to download each PDF. | | Spend limit | An amount per calendar month that triggers email alerts when the month’s spend crosses the thresholds you set, such as 80 % and 100 %. A spend limit only alerts; it doesn’t stop or refuse anything. Manage it with `setSpendLimit`, `clearSpendLimit` and `spendLimitStatus`. | | Usage and cost | What a project or the whole organization has used and what it costs, by hour or by day. Read it with the `usageCost` and `orgUsageCost` queries. Prices come from the [price list](/docs/pricing). | ## Billing details [#billing-details] Billing details are stored on the billing account. `register-organisation` sets them on the default billing account when you create the organization. To set or change them, call the `updateBillingAccountProfile` mutation in the `admin` namespace. It replaces every field at once: a field you leave out is cleared, not kept. The same rules apply as at registration: the invoice email must be a valid email address, the country must be an EU member state given as its ISO code, and every country except `DE` needs a VAT identification number. The `billingCountries` query lists the accepted countries and which need a VAT identification number. To rename a billing account, call `updateBillingAccountDisplayName`. The name appears in spend limit alert emails and can’t be empty. ## What you can do [#what-you-can-do] - [Add a payment method](/docs/platform/billing/payment-method) - [Give someone access to billing](/docs/platform/billing/billing-access) - [Charge a project to another billing account](/docs/platform/organizations/projects#change-a-projects-billing-account) Billing accounts, payment methods, invoices, spend limits and cost reports are available through the GraphQL API in the `admin` namespace. The CLI doesn’t cover them. ## Related [#related] - [Pricing](/docs/pricing) - [Organizations and projects](/docs/platform/organizations) - [`PAYMENT_METHOD_REQUIRED`](/docs/platform/reference/errors#payment_method_required) # Add a payment method Add a card to a billing account on the payment provider's hosted page, confirm it, and check paymentMethodStatus so the account's projects can create billable resources. A project can create billable resources only once its billing account has a verified payment method. You enter the card on the payment provider’s hosted page; card details never pass through Origin Cloud. ## Before you begin [#before-you-begin] - The organization ID and the ID of the project you want to unblock. - The `roles/billing/administrator` or `roles/billing/user` role on the organization. Whoever created the organization has the first one. The Owner role alone isn’t enough. See [Billing access](/docs/platform/billing/billing-access). To look up which billing account a project is charged to, you also need read access to the project, such as `roles/viewer`. - A way to call the GraphQL API, for example `curl` with your CLI token. See [Use the GraphQL API](/docs/platform/access/api). ## When a payment method is needed [#when-a-payment-method-is-needed] A billing account’s `paymentMethodStatus` is one of three values: | `paymentMethodStatus` | Meaning | | --- | --- | | `NONE` | No verified payment method. Billable resources are refused. | | `VERIFIED` | A payment method is on file and verified. | | `NOT_REQUIRED` | Billing is arranged with Origin Cloud directly, and no payment method is needed. | While the status is `NONE`, these operations in the account’s projects are refused with `PAYMENT_METHOD_REQUIRED`: - [Launch an instance](/docs/compute/instances/launch) - Create, import or grow a volume - Create a snapshot - Allocate a Floating IP - Create a NAT gateway Creating VPCs, subnets, security groups and other network configuration doesn’t need a payment method, so you can set up your network first, once the organization is `ACTIVE`: creating a VPC, including the default VPC, is refused until then. The organization must also be `ACTIVE` for the operations above. See [Organization review status](/docs/platform/organizations/review-status). ## Add the payment method [#add-the-payment-method] The steps send GraphQL requests with `curl`. Each request uses this pattern, with the request body on standard input: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ --data @- <<'EOF' EOF ``` 1. Find the billing account the project is charged to, and its current status: ```json { "query": "query($org: OrgId!, $p: ProjectId!) { admin { project(orgId: $org, projectId: $p) { billingAccountId } billingAccounts(input: {orgId: $org}) { billingAccountId displayName paymentMethodStatus } } }", "variables": { "org": "", "p": "" } } ``` If the project’s billing account is `VERIFIED` or `NOT_REQUIRED`, you’re done. 1. Start the setup on that billing account: ```json { "query": "mutation($org: OrgId!, $ba: BillingAccountId!) { admin { startPaymentMethodSetup(input: {orgId: $org, id: $ba}) { redirectUrl } } }", "variables": { "org": "", "ba": "" } } ``` The response contains a `redirectUrl`. 1. Open the `redirectUrl` in your browser and enter the card details. When you finish, the page returns you to the Origin Cloud console. 1. Confirm the setup: ```json { "query": "mutation($org: OrgId!, $ba: BillingAccountId!) { admin { confirmPaymentMethodSetup(input: {orgId: $org, id: $ba}) { paymentMethodStatus paymentMethodBrand paymentMethodLast4 } } }", "variables": { "org": "", "ba": "" } } ``` The platform checks the result with the payment provider. Returning to the console alone proves nothing. 1. Verify that `paymentMethodStatus` is `VERIFIED`. The response also shows the card brand and its last four digits. Example output (illustrative): ```json { "data": { "admin": { "confirmPaymentMethodSetup": { "paymentMethodStatus": "VERIFIED", "paymentMethodBrand": "visa", "paymentMethodLast4": "4242" } } } } ``` Every project charged to this billing account can now create billable resources. Send any request that was refused with `PAYMENT_METHOD_REQUIRED` again, unchanged. ## If the confirmation fails [#if-the-confirmation-fails] Both mutations fail with `BAD_REQUEST` naming `billing_account_id` in these cases: - The checkout wasn’t completed. You left the hosted page before finishing, or the card was declined. Finish the hosted page, or start again from step 2. - No setup is in progress. Nothing was started, or the setup was already confirmed. Check `paymentMethodStatus`: if it’s `VERIFIED`, you’re done. - The account needs no payment method. Its status is `NOT_REQUIRED`. Starting again always works and replaces any unfinished setup. ## Replace the payment method [#replace-the-payment-method] Run the same steps on a billing account that is already `VERIFIED`. The new card replaces the old one when you confirm it. Until then, the old card stays in place. ## Related [#related] - [Billing](/docs/platform/billing) - [Billing access](/docs/platform/billing/billing-access) - [`PAYMENT_METHOD_REQUIRED`](/docs/platform/reference/errors#payment_method_required) # Get started with Origin Cloud Register an organization, add a payment method, launch your first instance with the origin CLI, log in to it over SSH, and clean up afterwards. This tutorial takes you from a new user account to a running Linux instance you log in to over SSH. You use the `origin` CLI for almost every step and the GraphQL API for the payment method. ## What you’ll build [#what-youll-build] You’ll end up with an organization that holds one project. In the project runs one instance, in the project’s default VPC, with a public IPv4 address that you connect to over SSH. The following diagram shows the end state. ## What you’ll learn [#what-youll-learn] - How to install the CLI and log in. - How to register an organization and read its review status. - How to create a project and add a payment method. - How to import a key pair, launch an instance and log in to it. - How to remove what you created. ## Before you begin [#before-you-begin] - An Origin Cloud user account. If you don’t have one, see [Step 0: Create your account](#step-0-create-your-account). - A Linux or macOS computer with `ssh`, `ssh-keygen` and `curl`. - Your company’s billing details: postal address, invoice email address, contact person and, outside Germany, a VAT identification number. The billing address must be in an EU member state. - A credit or debit card for the payment method. ## Cost [#cost] The instance, its root volume and its public IPv4 address are billable for as long as they exist. Registering an organization, creating a project and the default VPC cost nothing. If you follow [Clean up](#clean-up) right after the tutorial, you pay for a few minutes of usage. For current rates, see [Pricing](/docs/pricing). At list prices of 13 October 2026, in EUR excluding VAT, 15 minutes cost about €0.02: | Item | List price | 15 minutes | | --- | --- | --- | | Instance, `gp1.core.2` | €0.0551 per hour | about €0.014 | | Root volume, `gp1`, for example 20 GiB | €0.00009589 per GiB-hour | about €0.0005 | | Public IPv4 address (Floating IP) | €0.00009537 per minute | about €0.0014 | The root volume’s size is the image’s own size. Metric samples the platform collects from the running instance, and traffic out to the internet (€0.09 per GB), add fractions of a cent here. ## Step 0: Create your account [#step-0-create-your-account] Create your Origin Cloud user account at [console.origincloud.eu](https://console.origincloud.eu). The CLI, the API and the console all use this account: in step 1 you log in to the CLI with it. ## Step 1: Install the CLI and log in [#step-1-install-the-cli-and-log-in] 1. Install the `origin` CLI. See [Install the CLI](/docs/platform/access/cli#install-the-cli). 1. Log in. Your browser opens the Origin Cloud login page: ```sh origin id login ``` On a machine without a browser, use `origin id login --device` instead. See [Log in](/docs/platform/access/cli#log-in). ## Step 2: Register your organization [#step-2-register-your-organization] 1. Register the organization with its billing details. Add `--vat-id ` if the billing address is outside Germany: ```sh origin admin register-organisation \ --name "Example GmbH" \ --street "Example Street 1" \ --city Berlin \ --postal-code 10115 \ --country DE \ --invoice-email billing@example.com \ --contact-person "Jane Doe" ``` 1. Note the `orgId` in the output, for example `0a1b2c3d4e5f`. You’re now the organization’s Owner and its billing administrator. For details and the other way to create an organization, see [Create an organization](/docs/platform/organizations/create). ## Step 3: Check the review status [#step-3-check-the-review-status] 1. Read the organization’s status: ```sh origin admin get-organisation --id ``` - `ACTIVE`: continue with the next step. - `PENDING_REVIEW`: the platform operator reviews the organization. You get an email when it’s approved. Continue with steps 4 to 6 in the meantime; only step 7 needs an active organization. - `REJECTED`: the decision is final, and you can’t continue. For what each status allows, see [Organization review status](/docs/platform/organizations/review-status). ## Step 4: Create a project [#step-4-create-a-project] 1. Create a project: ```sh origin admin create-project --org-id --name "Getting started" ``` 1. Note the project’s `urn` and `projectId` in the output. The following steps pass the URN as `--project-urn`. Example output (illustrative): ```json { "admin": { "createProject": { "urn": "urn:origin:cloud:admin::0a1b2c3d4e5f::lumen-482910375", "orgId": "0a1b2c3d4e5f", "projectId": "lumen-482910375", "name": "Getting started" } } } ``` ## Step 5: Add a payment method [#step-5-add-a-payment-method] A new project is charged to your organization’s default billing account. Launching an instance is refused with `PAYMENT_METHOD_REQUIRED` until that billing account has a verified payment method. You start the setup through the API, enter the card on the payment provider’s page, and confirm it through the API. You need the `roles/billing/administrator` role, which you got in step 2, the `orgId` from step 2 and the `projectId` from step 4. The requests below are the same as on [Add a payment method](/docs/platform/billing/payment-method), which also covers failures and replacing a card. 1. Find the billing account the project is charged to, and its current status: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ --data @- <<'EOF' { "query": "query($org: OrgId!, $p: ProjectId!) { admin { project(orgId: $org, projectId: $p) { billingAccountId } billingAccounts(input: {orgId: $org}) { billingAccountId displayName paymentMethodStatus } } }", "variables": { "org": "", "p": "" } } EOF ``` Note the project’s `billingAccountId`. If that billing account’s `paymentMethodStatus` is already `VERIFIED` or `NOT_REQUIRED`, skip to step 6. 1. Start the setup on that billing account: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ --data @- <<'EOF' { "query": "mutation($org: OrgId!, $ba: BillingAccountId!) { admin { startPaymentMethodSetup(input: {orgId: $org, id: $ba}) { redirectUrl } } }", "variables": { "org": "", "ba": "" } } EOF ``` 1. Open the `redirectUrl` from the response in your browser and enter the card details. When you finish, the page returns you to the Origin Cloud console. Returning to the console doesn’t activate the card. You must still run the confirm request in the next step. Until you do, `paymentMethodStatus` stays `NONE` and step 7 fails with `PAYMENT_METHOD_REQUIRED`. 1. Confirm the setup: ```sh curl -sS https://api.origincloud.eu/graphql \ -H "$(origin id token --as-header --raw)" \ -H "Content-Type: application/json" \ --data @- <<'EOF' { "query": "mutation($org: OrgId!, $ba: BillingAccountId!) { admin { confirmPaymentMethodSetup(input: {orgId: $org, id: $ba}) { paymentMethodStatus paymentMethodBrand paymentMethodLast4 } } }", "variables": { "org": "", "ba": "" } } EOF ``` 1. Verify that `paymentMethodStatus` in the response is `VERIFIED`. If the confirmation fails with `BAD_REQUEST`, see [If the confirmation fails](/docs/platform/billing/payment-method#if-the-confirmation-fails). ## Step 6: Create a key pair [#step-6-create-a-key-pair] The instance accepts SSH logins only with the key pair you name at launch. In this step you create a key on your computer and import its public half. 1. Create a key on your computer: ```sh ssh-keygen -t ed25519 -f ~/.ssh/origin-getting-started -C getting-started ``` 1. Import the public key into your project: ```sh origin compute import-key-pair \ --project-urn \ --name getting-started \ --public-key "$(cat ~/.ssh/origin-getting-started.pub)" ``` 1. Note the key pair’s `urn` in the output. The private key never leaves your computer. To have the platform generate a key pair instead, see [Create a key pair](/docs/compute/key-pairs/create). ## Step 7: Launch an instance [#step-7-launch-an-instance] 1. Choose an instance type. Pick one whose `available` is `true`, for example `gp1.core.2`, the smallest type on sale: ```sh origin compute list-instance-types ``` 1. Choose an image. The list contains the platform-provided images and any of your own. Platform-provided images have the `__typename` `ComputePublicImage`. Pick one by its `description`, and note its `urn` and `defaultUser`: ```sh origin compute list-images --project-urn ``` 1. Launch the instance. Without `--subnet-urn`, it goes into the project’s default VPC, which the platform creates now, with an internet gateway and a public address for the instance: ```sh origin compute launch-instance \ --project-urn \ --image-urn \ --key-pair-urn \ --instance-type gp1.core.2 ``` 1. Note the instance’s `urn` and `loginUser` in the output. Example output (illustrative): ```json { "compute": { "launchInstance": { "urn": "urn:origin:cloud:compute:eu-central1:0a1b2c3d4e5f:lumen-482910375:i-79PVin5MmNc", "instanceId": "i-79PVin5MmNc", "instanceType": "gp1.core.2", "loginUser": "cloud", "status": "INITIALIZING" } } } ``` 1. Wait until the instance is running. Repeat this command until `status` is `RUNNING`: ```sh origin compute get-instance --instance-urn ``` The instance passes through `INITIALIZING` and `PENDING` first. To poll every 10 seconds until it stops changing, with `jq`: ```sh while :; do status="$(origin compute get-instance --instance-urn \ | jq -r '[.. | .status? | strings] | first')" echo "$status" case "$status" in RUNNING | FAILED) break ;; esac sleep 10 done ``` If the status is `FAILED`, read the instance’s `statusReason` and look it up in [Status reasons](/docs/compute/reference/status-reasons), then terminate the instance and launch again. If the host never confirms the start, an instance can stay `PENDING` for about 30 minutes before it becomes `FAILED`. See [Instance lifecycle](/docs/compute/instances/lifecycle#when-a-lifecycle-operation-fails). If the launch is refused, the error code tells you why. See [Error codes](/docs/platform/reference/errors). A refused launch creates nothing and costs nothing. Retry the same launch every 5 to 10 minutes. If a larger type such as `gp1.core.4` is `available`, launching that type instead may succeed sooner. ## Step 8: Connect to the instance [#step-8-connect-to-the-instance] The default VPC’s security group allows SSH from anywhere, so no firewall change is needed. Logins need the key pair’s private key; passwords are refused. To allow SSH from your own address only, see [Security groups](/docs/network/traffic-control/security-groups). 1. Find the instance’s public address. The platform assigned it as a Floating IP at launch; in a new project, it’s the only one listed. Note its `address`: ```sh origin network list-floating-ips --project-urn ``` If the project already has other Floating IPs, match the address to the instance’s network interface. With `jq`: ```sh nic="$(origin compute get-instance --instance-urn \ | jq -r '[.. | .networkInterfaceAttachments? // empty | .[].networkInterfaceUrn] | first')" origin network list-floating-ips --project-urn \ | jq -r --arg nic "$nic" '.. | objects | select(.networkInterfaceUrn? == $nic) | .address' ``` If the list is empty, the platform couldn’t assign a public address, for example because the public IP quota is used up. See [Limits](/docs/platform/reference/limits). 1. Log in as the instance’s `loginUser`, which you noted in step 7, with the private key from step 6: ```sh ssh -i ~/.ssh/origin-getting-started @ ``` `RUNNING` means the host started the instance; it doesn’t prove the guest’s network is up yet. If the login times out right after launch, wait a moment and try again. If it keeps failing, see [Can’t connect over SSH](/docs/compute/troubleshooting#cant-connect-over-ssh). 1. Verify that you’re on the instance. The login user has passwordless `sudo`: ```sh sudo whoami ``` Example output (illustrative): ```text root ``` ## Clean up [#clean-up] Remove what you created so it stops costing money. 1. Terminate the instance. Its root volume and network interface are deleted, and the auto-assigned public address is released with it: ```sh origin compute terminate-instance --instance-urn ``` 1. Delete the key pair: ```sh origin compute delete-key-pair --key-pair-urn ``` 1. Verify that the instance reaches `TERMINATED`: ```sh origin compute get-instance --instance-urn ``` The default VPC stays in the project. It costs nothing, and the next launch without a subnet reuses it. To delete the project as well, delete the default VPC first with `origin network delete-vpc`, then the project. See [Manage projects](/docs/platform/organizations/projects). ## Next steps [#next-steps] - [Compute](/docs/compute): instance lifecycle, images and instance types. - [Storage](/docs/storage): add volumes and take snapshots. - [Network](/docs/network): build your own VPC with private subnets. - [IAM](/docs/iam): invite your team and assign roles. - [Service accounts](/docs/iam/service-accounts): automate with the API. # What is Origin Cloud? Origin Cloud runs virtual machines, block storage and private networks in European data centers. Learn how organizations, projects and resources fit together. Origin Cloud is an infrastructure cloud: it runs virtual machines, block storage and private networks for you, so you don't buy or operate the hardware underneath. You create resources on demand, pay for what you use, and remove them when you're done. Every resource belongs to a project, and every project belongs to your organization. An organization is your company's account. It holds your members and their roles, your billing accounts, and your projects. A project groups the resources of one application or environment, and is charged to one billing account. A resource is anything you create in a project: an instance, a volume, a VPC, a security group and so on. You reach your organization through the console, the origin CLI or the GraphQL API. ## Features [#features] - **Compute**: Virtual machines, called instances, launched from an image at a size you choose. See [Compute](/docs/compute). - **Storage**: Durable block volumes and snapshots for your instances. See [Storage](/docs/storage). - **Network**: Private VPCs, internet access, Floating IPs, NAT gateways, security groups and DNS. See [Network](/docs/network). - **IAM**: Members, roles, service accounts and the audit log of your organization. See [IAM](/docs/iam). - **Observability**: Metrics for your instances, volumes and network interfaces. See [Observability](/docs/observability). - **Pricing**: The public list price of every billable product. See [Pricing](/docs/pricing). - **Organizations and projects**: Your account, its review status, and the projects you create resources in. See [Organizations](/docs/platform/organizations). - **Billing**: Billing accounts, payment methods, and who may manage them. See [Billing](/docs/platform/billing). ## Ways to access Origin Cloud [#ways-to-access-origin-cloud] - **Origin Cloud console**: The web interface, for working with your organization in a browser. - **origin CLI**: A command-line tool for Linux and macOS that covers organizations, projects, compute, storage, network and IAM. See [Use the CLI](/docs/platform/access/cli). - **GraphQL API**: Every operation the console and the CLI use, at `https://api.origincloud.eu/graphql`. See [Use the GraphQL API](/docs/platform/access/api). For a comparison, see [Ways to access Origin Cloud](/docs/platform/access). ## Before you can create resources [#before-you-can-create-resources] Three things stand between a new organization and its first instance: - The organization must be `ACTIVE`. A new organization is either activated immediately or reviewed first. See [Organization review status](/docs/platform/organizations/review-status). - The project's billing account needs a verified payment method before you create anything billable. See [Add a payment method](/docs/platform/billing/payment-method). - Each organization has quotas on what it can hold at once. See [Limits](/docs/platform/reference/limits). ## Pricing [#pricing] Origin Cloud bills by usage. Each billable product has a public list price per unit, such as an hourly rate for an instance type or a rate per gigabyte of network traffic. See [Pricing](/docs/pricing). For how your organization pays, see [Billing](/docs/platform/billing). ## Next steps [#next-steps] - [Get started with Origin Cloud](/docs/platform/getting-started): register an organization and launch your first instance. - [Reference](/docs/platform/reference): CLI commands, error codes and limits. # Create an organization Register an organization with its billing details in one step, or create it from its name alone and add the billing details to its default billing account later. Create an organization to get an account your company’s projects, members and billing live in. You can register it with its billing details in one step, or create it from its name alone and add the billing details afterwards. ## Before you begin [#before-you-begin] - An Origin Cloud user account, logged in with the CLI. To create an account, see [Create your account](/docs/platform/getting-started#step-0-create-your-account); to log in, see [Use the CLI](/docs/platform/access/cli). Any signed-in user can create an organization. - The billing details to invoice: a postal address, the email address invoices go to, the person they’re addressed to and, if the organization has one, a VAT identification number. - The billing address’s country is one of the 27 EU member states, given as an ISO 3166-1 alpha-2 code such as `DE` or `AT`. Outside Germany, invoicing is business to business only, so a VAT identification number is required for every country except `DE`. ## Register an organization [#register-an-organization] Registering creates the organization and stores the billing details on its default billing account, so it can be invoiced from the start. 1. Register the organization: ```sh origin admin register-organisation \ --name "Example GmbH" \ --street "Example Street 1" \ --city Berlin \ --postal-code 10115 \ --country DE \ --invoice-email billing@example.com \ --contact-person "Jane Doe" ``` Add `--vat-id ` if the organization has a VAT identification number. It’s required for every country except `DE`. Example output (illustrative): ```json { "admin": { "registerOrganisation": { "id": "...", "urn": "urn:origin:cloud:admin::::0a1b2c3d4e5f", "orgId": "0a1b2c3d4e5f", "name": "Example GmbH", "status": "PENDING_REVIEW", "createdAt": "2026-10-03T09:12:44Z", "createdBy": "user:..." } } } ``` 1. Note the `orgId`. Most commands take it as `--org-id`. 1. Verify that the organization exists and read its status: ```sh origin admin get-organisation --id 0a1b2c3d4e5f ``` `status` is `ACTIVE` or `PENDING_REVIEW`. For what each means, see [Organization review status](/docs/platform/organizations/review-status). The request is refused, and nothing is created, if the invoice email isn’t a valid email address, the country isn’t supported, or a required VAT identification number is missing. The error is `BAD_REQUEST` and names the field: `invoice_email`, `country` or `vat_id`. With the API, use the `registerOrganisation` mutation in the `admin` namespace. It takes the same details, with the address as a `billingAddress` object. ## Create an organization from its name alone [#create-an-organization-from-its-name-alone] Use this path if someone else adds the billing details later. 1. Create the organization: ```sh origin admin create-organisation --name "Example GmbH" ``` 1. Add the billing details to its default billing account with the `updateBillingAccountProfile` mutation. Until then, the organization can’t be invoiced. See [Billing](/docs/platform/billing). Both paths end in the same state; registering does it in one call. ## What happens when you create an organization [#what-happens-when-you-create-an-organization] - You become the organization’s Owner (`roles/owner`) and its billing administrator (`roles/billing/administrator`), both organization-wide. See [Billing access](/docs/platform/billing/billing-access). - The organization gets a default billing account named `default`. With `register-organisation`, it carries your billing details. - The organization is either activated immediately or placed under review. You get an email that the registration was received, and another when it’s approved or rejected. See [Organization review status](/docs/platform/organizations/review-status). ## Next steps [#next-steps] - [Create a project](/docs/platform/organizations/projects#create-a-project) - [Add a payment method](/docs/platform/billing/payment-method) ## Related [#related] - [`register-organisation` reference](/docs/platform/reference/cli#register-organisation) - [`create-organisation` reference](/docs/platform/reference/cli#create-organisation) # Organizations and projects An organization is your company's Origin Cloud account and holds your projects, members and billing accounts. Learn how they relate and what you can manage. An organization is your company’s account on Origin Cloud. It holds the people and service accounts that can act in it, the billing accounts it pays through, and the projects your resources live in. You register an organization once; after that you work inside its projects. The following list shows what an organization holds and how a project connects resources to billing. - An **organization** holds its **members and roles**, its **billing accounts** and its **projects**. - A **project** holds **resources** and is charged to one **billing account**. ## Key concepts [#key-concepts] | Concept | What it is | | --- | --- | | Organization | Your company’s account. It has a name, an ID such as `0a1b2c3d4e5f`, and a review status. Whoever creates it becomes its Owner. See [Create an organization](/docs/platform/organizations/create). | | Review status | Whether the organization may create billable resources: `PENDING_REVIEW`, `ACTIVE` or `REJECTED`. See [Organization review status](/docs/platform/organizations/review-status). | | Project | A container for the resources of one application, team or environment. Every instance, volume and VPC belongs to exactly one project. Roles can be granted on a single project. See [Manage projects](/docs/platform/organizations/projects). | | Billing account | What a project is charged to. Every organization starts with one billing account, named `default`, and every project is linked to one. See [Billing](/docs/platform/billing). | | Members | The people and service accounts that hold a role in the organization. See [IAM](/docs/iam). | ## What you can do [#what-you-can-do] - [Create an organization](/docs/platform/organizations/create) - [Check your organization’s review status](/docs/platform/organizations/review-status) - [Create, rename and delete projects](/docs/platform/organizations/projects) - [Add a payment method](/docs/platform/billing/payment-method) - [Invite members and assign roles](/docs/iam/manage-members) ## Limits and quotas [#limits-and-quotas] Quotas apply per organization and, if you set budgets, per project. See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Billing](/docs/platform/billing) - [IAM](/docs/iam) - [Platform CLI commands](/docs/platform/reference/cli) # Manage projects Create, list, rename and delete the projects in your organization, find a project's URN, change the billing account a project is charged to, and delete an organization. Every resource lives in a project, so you create at least one project before you launch anything. Use separate projects to keep applications or environments apart, to grant roles on one of them only, or to charge them to different billing accounts. ## Before you begin [#before-you-begin] - An organization, and its ID. See [Create an organization](/docs/platform/organizations/create). - The `origin` CLI, logged in. See [Use the CLI](/docs/platform/access/cli). - The Owner role (`roles/owner`) on the organization, or a role with the `admin.project.*` permissions. See [Roles](/docs/iam/roles). You can create and manage projects while the organization is still under review. ## Create a project [#create-a-project] 1. Create the project: ```sh origin admin create-project --org-id --name "Web shop" ``` To choose how the project ID starts, add `--id-prefix `, for example `--id-prefix shop`. The platform appends random digits. A prefix has at least two characters, uses lowercase letters, digits and hyphens, and starts with a letter. Without a prefix, the platform picks a random word. Example output (illustrative): ```json { "admin": { "createProject": { "id": "...", "urn": "urn:origin:cloud:admin::0a1b2c3d4e5f::shop-4829103756", "orgId": "0a1b2c3d4e5f", "projectId": "shop-4829103756", "name": "Web shop", "createdAt": "2026-10-03T09:20:01Z", "createdBy": "user:..." } } } ``` 1. Note the `urn`. Compute, storage and network commands take it as `--project-urn`. You can also build it from the IDs: `urn:origin:cloud:admin::::`. 1. Verify that the project is listed: ```sh origin admin list-projects --org-id ``` A new project is charged to the organization’s default billing account. ## View a project [#view-a-project] ```sh origin admin get-project --org-id --id ``` ## Rename a project [#rename-a-project] Renaming changes the display name only. The project ID and URN stay the same. ```sh origin admin update-project --org-id --id \ --name "Web shop (production)" ``` To rename the organization, use `origin admin update-organisation --org-id --name `. ## Change a project’s billing account [#change-a-projects-billing-account] A project is always charged to exactly one billing account of its organization. To charge it to another one, call the `linkProjectToBillingAccount` mutation in the `admin` namespace with `orgId`, `projectId` and `billingAccountId`. It replaces the current link; there’s no way to leave a project without a billing account. This needs the `admin.project.attach` permission, which the Owner role has. It doesn’t need access to the billing account itself. See [Billing access](/docs/platform/billing/billing-access). ## Delete a project [#delete-a-project] Deleting a project is refused while it still owns any of these resources. Nothing is deleted on your behalf. - An instance that isn’t terminated. - An image or a key pair. - A volume or snapshot that isn’t deleted. - A NAT gateway or an allocated Floating IP. - A VPC, including the default VPC that a launch created. 1. Delete every resource in the project: terminate its instances, delete its images, key pairs, volumes and snapshots, delete its NAT gateways, release its Floating IPs, and delete its VPCs. 1. Delete the project: ```sh origin admin delete-project --org-id --id ``` 1. Verify that the project is no longer listed by `origin admin list-projects --org-id `. If a resource remains, the request fails with `BAD_REQUEST`, naming every kind of resource the project still owns, in the order to remove them: ```text invalid input on field project_id: cannot delete project: it still owns at least one instance, one snapshot and one Floating IP ``` Deleting a project also removes the quota budgets you set on it, and every role assignment scoped to it, for every member and service account. Org-wide role assignments are unaffected. See [Role assignments and scopes](/docs/iam/access-model#role-assignments-and-scopes). ## Delete an organization [#delete-an-organization] An organization can be deleted only when it has no projects left. Delete every project first, then run: ```sh origin admin delete-organisation --org-id ``` While projects remain, the request fails with `BAD_REQUEST` and says how many. Billing accounts that no project is linked to don’t block the deletion. ## Related [#related] - [Organizations and projects](/docs/platform/organizations) - [Platform CLI commands](/docs/platform/reference/cli) - [Limits](/docs/platform/reference/limits) # Organization review status A new organization is activated at once or reviewed first, depending on platform capacity. Learn what each status allows, which emails you get, and how to check it. Every organization has a review status that decides whether it may create billable resources. A new organization is either activated the moment you create it or placed under review, depending on how much spare capacity the platform has at that moment. You don’t choose which, and there’s nothing to opt into. The following table shows the statuses and the transitions between them. | From | Event | To | | --- | --- | --- | | New organization | Created with spare capacity | `ACTIVE` | | New organization | Created without spare capacity | `PENDING_REVIEW` | | `PENDING_REVIEW` | Approved | `ACTIVE` | | `PENDING_REVIEW` | Rejected | `REJECTED` | ## Statuses [#statuses] | Status | Meaning | Can create billable resources | | --- | --- | --- | | `PENDING_REVIEW` | The organization waits for a decision by the platform operator. | No | | `ACTIVE` | The organization is approved. | Yes, once its billing account has a payment method | | `REJECTED` | The organization was rejected. The decision is final. | No | The decision is the platform operator’s. There’s no way to approve your own organization, or to request a decision, through the console, the CLI or the API. ## What an organization under review can do [#what-an-organization-under-review-can-do] An organization under review can be administered normally. You can create and delete projects, invite and remove members, assign roles, create service accounts, and manage billing accounts and payment methods. What it can’t do is create resources that cost money. These operations check the status and are refused until the organization is `ACTIVE`: - [Launch an instance](/docs/compute/instances/launch) - Create, import or grow a volume - Create a snapshot - Create a VPC, including the default VPC a first launch creates - Allocate a Floating IP - Create a NAT gateway The refusal is a `BAD_REQUEST` error that names the `org_id` field, for example: ```text invalid input on field org_id: organisation is pending_review, not active - it cannot create resources until an operator approves it ``` Being `ACTIVE` isn’t the last check. Most of these operations also need a verified payment method on the project’s billing account. See [Add a payment method](/docs/platform/billing/payment-method). ## Emails [#emails] The person who created the organization gets these emails: - When the organization is created: confirmation that the registration was received. - When it’s approved, including an immediate activation: an approval email. - When it’s rejected: a rejection email. An organization created by a service account has no email address to notify, so no emails are sent. ## Check the status [#check-the-status] The status is the `status` field of the organization. Read it with the CLI: ```sh origin admin get-organisation --id ``` `origin admin list-organisations` shows the status of every organization you can access. With the API, read `status` from the `organisation` or `organisations` query in the `admin` namespace. ## Related [#related] - [Create an organization](/docs/platform/organizations/create) - [Add a payment method](/docs/platform/billing/payment-method) - [Error codes](/docs/platform/reference/errors) # Platform CLI commands Every origin id, origin admin and origin config command with its flags: log in, manage organizations and projects, and set CLI profile values. This page lists every `origin id`, `origin admin` and `origin config` command, and the options every `origin` command accepts. For installing and configuring the CLI, see [Use the CLI](/docs/platform/access/cli). ## Global options [#global-options] Every `origin` command accepts these options before the command group. | Option | Description | | --- | --- | | `--config ` | Accepted, but doesn’t change which profile the CLI reads. | | `--api ` | GraphQL API endpoint to send requests to. Defaults to `https://api.origincloud.eu/graphql`. | | `--debug` | Accepted, but doesn’t change the output. | The CLI’s own help text still describes `--config` as choosing a configuration file and `--debug` as printing debugging information. Neither has that effect in v1.9.15. See [Global options](/docs/platform/access/cli#global-options). ## login [#login] Log in through your browser, or with a code on another device. Opens the Origin Cloud login page in your browser and waits for you to log in there. With `--device`, prints an address and a code to approve on any other device instead, for machines without a browser such as an SSH session. The CLI never asks for your password. ```sh origin id login [OPTIONS] ``` | Option | Required | Description | | --- | --- | --- | | `--device` | no | Log in by approving a code on another device, instead of opening a browser on this machine. | ## token [#token] Print the access token of the current login session, for calling the GraphQL API directly. ```sh origin id token [OPTIONS] ``` | Option | Required | Description | | --- | --- | --- | | `--as-header` | no | Print the token as an HTTP Authorization header (`Authorization: Bearer `). | | `--raw` | no | Print plain text with no JSON envelope, for direct use in shell one-liners (e.g. `curl -H "$(origin id token --as-header --raw)"`) | ## create-organisation [#create-organisation] Create organisation from its name alone; its billing details are added afterwards on its default billing account. [`register-organisation`](#register-organisation) does both in one step. ```sh origin admin create-organisation --name ``` | Option | Required | Description | | --- | --- | --- | | `--name ` | yes | Name of the organization. | ## register-organisation [#register-organisation] Register organisation. The billing details become its default billing account, so the organisation is billable from the start. ```sh origin admin register-organisation [OPTIONS] --name --street --city --postal-code --country --invoice-email --contact-person ``` | Option | Required | Description | | --- | --- | --- | | `--name ` | yes | Name of the organization. | | `--street ` | yes | Street and number of the billing address. | | `--city ` | yes | City of the billing address. | | `--postal-code ` | yes | Postal code of the billing address. | | `--country ` | yes | Country of the billing address. | | `--invoice-email ` | yes | Email address invoices are sent to. | | `--contact-person ` | yes | Person invoices are addressed to. | | `--vat-id ` | no | VAT identification number, if any. | ## list-organisations [#list-organisations] List accessible organisations. ```sh origin admin list-organisations ``` This command takes no options. ## get-organisation [#get-organisation] Get an organization by its id or URN. ```sh origin admin get-organisation --id ``` | Option | Required | Description | | --- | --- | --- | | `--id ` | yes | Id of the organisation. | ## create-project [#create-project] Create a project in an organization. ```sh origin admin create-project [OPTIONS] --name --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--name ` | yes | Name of the project. | | `--id-prefix ` | no | Prefix of the project id. | | `--org-id ` | yes | ID of the organisation. | ## list-projects [#list-projects] List accessible projects. ```sh origin admin list-projects --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## get-project [#get-project] Get a project by its id or URN. ```sh origin admin get-project --org-id --id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--id ` | yes | Id of the project. Use with org-id. | ## update-organisation [#update-organisation] Rename an organisation. ```sh origin admin update-organisation --org-id --name ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--name ` | yes | New name. | ## delete-organisation [#delete-organisation] Delete an organisation. Refuses unless it has zero projects. ```sh origin admin delete-organisation --org-id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | ## update-project [#update-project] Rename a project. ```sh origin admin update-project --org-id --id --name ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--id ` | yes | Id of the project. | | `--name ` | yes | New name. | ## delete-project [#delete-project] Delete a project. Refuses while it still owns any resource (instance, image, key pair, volume, snapshot, NAT gateway, Floating IP, VPC) and names each kind left ```sh origin admin delete-project --org-id --id ``` | Option | Required | Description | | --- | --- | --- | | `--org-id ` | yes | ID of the organisation. | | `--id ` | yes | Id of the project. | ## profile [#profile] Show the values stored in the local CLI profile. ```sh origin config profile ``` This command takes no options. ## profile-set [#profile-set] Set a value in the local CLI profile. ```sh origin config profile-set ``` This command takes no options. # Error codes Every error code the Origin Cloud API returns, with what it means, what commonly causes it, and what to do. Branch on the code, never on the message. Every error the API returns carries a stable code. This page lists each code with its meaning, common causes and what to do. The codes are shared by every service, so the same code means the same thing whether it comes from compute, storage, network, IAM or administration. ## How errors are returned [#how-errors-are-returned] In the GraphQL API, a failed operation returns an `errors` array. Each error has a human-readable `message` and, in `extensions`, three fields: | Field | Meaning | | --- | --- | | `code` | The stable, machine-readable code. Branch on it. Messages can change wording; codes don’t. | | `retryable` | Whether sending the identical request again can succeed. It’s deliberately conservative: only conditions that clear by themselves are retryable. | | `correlationId` | An ID for your request. Quote it when you contact support: it ties your error to the platform’s own record of what happened. | ```json { "errors": [{ "message": "invalid input on field quota: organisation quota exceeded: vCPU usage is 38, requesting 4 more would exceed the limit of 40", "extensions": { "code": "BAD_REQUEST", "retryable": false, "correlationId": "4bf92f3577b34da6a3ce929d0e0e4736" } }] } ``` The `origin` CLI prints the message followed by the code in parentheses and the correlation id, and exits with `1`. See [Use the CLI](/docs/platform/access/cli). ## Refusals and faults [#refusals-and-faults] Every code is one of two kinds, and the difference tells you who has to act: - A refusal you can act on. The platform understood the request and declined it, for a reason the message states: invalid input, missing permission, an exhausted quota, a missing payment method, no capacity right now. Nothing was created or changed. Fix what the message names, or wait where the code says so, then send the request again. - A platform fault. Something inside the platform failed. The message is deliberately generic and names no internal detail. Nothing about your request is wrong; retry if the code is retryable, and otherwise report the `correlationId`. | Code | Kind | Retryable | | --- | --- | --- | | `UNAUTHORIZED` | Refusal | No | | `FORBIDDEN` | Refusal | No | | `BAD_REQUEST` | Refusal | No | | `NOT_FOUND` | Refusal | No | | `CONFLICT` | Refusal | No | | `PAYMENT_METHOD_REQUIRED` | Refusal | No | | `PRODUCT_UNAVAILABLE` | Refusal | No | | `INSUFFICIENT_CAPACITY` | Refusal | Yes | | `SERVICE_UNAVAILABLE` | Fault | Yes | | `INTERNAL_SERVER_ERROR` | Fault | No | | `SERVER_ERROR` | Fault | No | The codes below are ordered the same way: refusals first, then faults. ## UNAUTHORIZED [#unauthorized] **Meaning:** The request carried no usable credentials. The message is `Authorization required`. **Common causes:** - No `Authorization` header, or a header that doesn’t start with `Bearer`. - An access token that has expired. - A token that wasn’t issued by Origin Cloud, or was altered. **What to do:** Get a fresh access token and send the request again. With the CLI, run `origin id login`. With a service account, request a new token with the client credentials grant. See [Use the GraphQL API](/docs/platform/access/api). ## FORBIDDEN [#forbidden] **Meaning:** Your credentials are valid, but you lack the permission the operation needs. The message names the permission and the resource, for example `This operation requires permission compute.instance.launch on `. **Common causes:** - You have no role in the organization or project, or a role without that permission, such as `roles/viewer` for a write. - A billing operation without a billing role. The Owner role doesn’t include access to billing accounts. - A service account without a role. A new service account has none. - Assigning, revoking or inviting with a role that carries permissions you don’t hold yourself at that scope, or removing a member who holds one. The message names the role and some of the permissions you lack. See [Who can assign a role](/docs/iam/access-model#who-can-assign-a-role). **What to do:** Ask an Owner of the organization to grant you a role that includes the named permission, then send the request again. See [Built-in roles](/docs/iam/roles) and, for billing, [Billing access](/docs/platform/billing/billing-access). ## BAD_REQUEST [#bad_request] **Meaning:** The request is malformed, failed validation, or was refused by a check the request itself can’t pass as it stands. The message names the field, in the form `invalid input on field : `. **Common causes:** - A value that fails validation, such as a malformed URN, an invalid email address, or a size below the minimum. - A request the resource can’t accept in its current form, such as changing the type of an instance that isn’t stopped, or deleting a VPC’s default security group. - An exhausted quota. The field is `quota`, and the message names the scope, the dimension, the current usage and the limit. See [Limits](/docs/platform/reference/limits). - An organization that isn’t `ACTIVE`. The field is `org_id`. See [Organization review status](/docs/platform/organizations/review-status). - A project or organization delete that is blocked by what it still owns. The field is `project_id` or `org_id`. - A billing detail that isn’t accepted: `invoice_email`, `country`, `vat_id` or `display_name`. - A payment method setup that wasn’t completed, isn’t in progress, or isn’t needed. The field is `billing_account_id`. See [Add a payment method](/docs/platform/billing/payment-method). - A VPC without an address range, when the platform has no default range left to pick. The field is `ipv4_cidr`. **What to do:** Read the field and cause in the message, change the request accordingly, and send it again. For a quota, free up usage, set a higher project budget, or ask for a higher organization quota. Sending the identical request again doesn’t help. ## NOT_FOUND [#not_found] **Meaning:** The resource doesn’t exist, or you can’t see it. The platform doesn’t distinguish the two, so a missing resource doesn’t reveal whether it exists in someone else’s project. **Common causes:** - A typo in an ID or URN, or a URN from another project or organization. - A resource that was deleted. - A resource in a project you have no role in. **What to do:** Check the ID or URN against a fresh list of your resources. Don’t send the identical request again. ## CONFLICT [#conflict] **Meaning:** The request conflicts with the resource’s current state. The message says what’s in the way. **Common causes:** - An action the resource’s current state doesn’t allow, such as resizing a volume that isn’t `AVAILABLE` or `INUSE`, or starting an instance that is still initializing. - A resource that still has a live dependent, such as a volume that is still attached to an instance, or a subnet that still has an attached network interface. The message names what to detach or delete first. - A bounded address space that has run out, such as a subnet with no IPv4 addresses left. The message names what frees or replaces it. - Revoking the last organization-wide Owner role. **What to do:** Resolve the conflict the message describes, for example by detaching the dependent or waiting for the resource to reach a state that allows the action, then send the request again. Retrying the identical request without changing anything doesn’t help. ## PAYMENT_METHOD_REQUIRED [#payment_method_required] **Meaning:** The request would create something that costs money, and the project’s billing account has no verified payment method. Nothing about the request is wrong. The message is `a verified payment method is required to create billable resources - add one to this project's billing account`. **Common causes:** - Launching an instance, creating, importing or growing a volume, creating a snapshot, allocating a Floating IP or creating a NAT gateway in a project whose billing account has `paymentMethodStatus` `NONE`. - A project linked to a different billing account than the one you added a payment method to. **What to do:** Add a payment method to the project’s billing account, then send the identical request again. See [Add a payment method](/docs/platform/billing/payment-method). Waiting doesn’t help. ## PRODUCT_UNAVAILABLE [#product_unavailable] **Meaning:** The product you selected exists and has a price, but isn’t on sale right now. Nothing about the request is malformed and nothing is broken. The message names the product you asked for and the ones you can choose instead. **Common causes:** - An instance type that is no longer offered, when you launch an instance, start one that runs as that type, or change an instance’s type. - A storage class that is published in the price list but not offered. **What to do:** Pick one of the alternatives the message names. For instance types, choose one whose `available` is `true` in `origin compute list-instance-types`; for storage classes, use `origin storage list-storage-classes`. Retrying doesn’t help: a product becomes available by a decision, not over time. ## INSUFFICIENT_CAPACITY [#insufficient_capacity] **Meaning:** The platform has no room for the request right now: no machine can place an instance of the requested type. Nothing about the request is wrong; the platform is full, not broken. The message names the instance type and what was short, such as vCPU or memory. **Common causes:** - Launching or starting an instance of a type whose machines are full. - Launching a type that no machine serves. **What to do:** Nothing was created by the refused request. Send the identical request again later, for example every 5 to 10 minutes, or choose a different instance type whose `available` is `true`. ## SERVICE_UNAVAILABLE [#service_unavailable] **Meaning:** A part of the platform the request depends on was unavailable. The message is `Service temporarily unavailable. Please retry.` **Common causes:** - A short interruption inside the platform. - A metrics query that took too long to answer. **What to do:** Send the request again after a short wait, with increasing waits between attempts. If it keeps failing, report the `correlationId`. ## INTERNAL_SERVER_ERROR [#internal_server_error] **Meaning:** The request failed inside the platform. The message is `Internal server error.` and deliberately carries no detail. **Common causes:** - A fault in the platform. Nothing about your request is known to be wrong. **What to do:** Report the `correlationId` to Origin Cloud support. The identical request may succeed later, but this code doesn’t say so: check whether the operation took effect before you send it again. ## SERVER_ERROR [#server_error] **Meaning:** A part of the platform that Origin Cloud operates refused the platform’s own credentials. It’s a platform misconfiguration that an operator has to correct. The message names the affected component, for example `The platform's identity service is misconfigured.` **Common causes:** - A platform misconfiguration affecting operations that reach the identity service, such as creating a service account. **What to do:** Report the `correlationId` to Origin Cloud support. Retrying doesn’t help until the platform is fixed. ## Codes not listed here [#codes-not-listed-here] New codes can be added; existing codes never change meaning. If your client receives a code it doesn’t know, use the `retryable` flag to decide whether to retry, and report the `correlationId`. ## Errors without a code [#errors-without-a-code] Errors that the GraphQL layer raises before an operation runs carry no code. They occur when the query has a syntax error, names a field or argument that doesn’t exist, or passes a value of the wrong type, such as a malformed URN in a `Urn` argument. The message describes the problem. Fix the query; these errors never succeed on retry. ## Failures after the request was accepted [#failures-after-the-request-was-accepted] Some operations return as soon as the request is accepted and finish later, such as launching an instance. If the later work fails, the reason is recorded on the resource, for example in an instance’s `statusReason`. A refusal reads like the message the API would have returned. A platform fault reads as a generic sentence ending in its code, such as `(SERVICE_UNAVAILABLE)` or `(INTERNAL_SERVER_ERROR)`. See [Status reasons](/docs/compute/reference/status-reasons). ## Related [#related] - [Use the GraphQL API](/docs/platform/access/api) - [Limits](/docs/platform/reference/limits) # Platform reference Look up the platform CLI commands, every error code the API returns with what to do about it, and the quotas and hard limits that apply to your organization. These pages list everything of one kind in full. For explanations and procedures, start from [What is Origin Cloud?](/docs/platform). ## Pages [#pages] | Page | What it lists | | --- | --- | | [Platform CLI commands](/docs/platform/reference/cli) | Every `origin id`, `origin admin` and `origin config` command with its options, and the global options every command accepts. | | [Error codes](/docs/platform/reference/errors) | Every error code the API returns, what it means and what to do about it. The codes are shared by all services. | | [Limits](/docs/platform/reference/limits) | The quotas on what an organization and its projects can hold, how to read them, and the hard limits of the platform. | ## Reference pages of the other guides [#reference-pages-of-the-other-guides] - [`origin compute` commands](/docs/compute/reference/cli) - [`origin storage` commands](/docs/storage/reference/cli) - [`origin network` commands](/docs/network/reference/cli) - [`origin iam` commands](/docs/iam/reference/cli) - [Price list API](/docs/pricing/reference/price-list-api) - [Metrics](/docs/observability/reference/metrics) # Limits The quotas on what your organization and its projects can hold, how to read current usage against them, how to set project budgets, and the platform's hard limits. Quotas cap how much your organization can hold at once, such as instances, vCPUs or volume storage. They protect you from runaway automation and the platform from overload. This page lists every quota, how to read it, and the hard limits that apply regardless of quota. ## How quotas work [#how-quotas-work] Quotas apply at two levels, and both are checked on every request that consumes one: | Level | What it is | | --- | --- | | Organization quota | The limit for the whole organization. Origin Cloud sets it, and it can differ between organizations. To raise it, contact Origin Cloud support. | | Project budget | An optional limit you set on a single project, so one project can’t use up the whole organization’s allowance. A project has no budget until you set one; it’s then bounded only by the organization quota. A budget can’t exceed the organization quota for the same dimension, and the budgets of several projects may add up to more than the organization quota: they’re limits, not reservations. | Quotas count what exists now, not what you created over time. Deleting a resource frees its share of the quota at once. ## Read your quota [#read-your-quota] The `organisationQuota` query returns each limit together with current usage, counted at the moment you ask. Anyone with read access to the organization can read it. ```graphql query { admin { organisationQuota(orgId: "") { maxInstances currentInstances maxVcpu currentVcpu maxVolumeGib currentVolumeGib maxVpcs currentVpcs maxPublicIps currentPublicIps } } } ``` `projectQuota(orgId: "", projectId: "")` returns the same fields for one project. There, a `max*` field is `null` when the project has no budget for that dimension. The CLI doesn’t show quotas. ## Set a project budget [#set-a-project-budget] Set one dimension of a project’s budget with the `setProjectQuotaLimit` mutation, and remove it with `clearProjectQuotaLimit`. Both need the `admin.resource_quota.update` permission, which the Owner role has. ```graphql mutation { admin { setProjectQuotaLimit(input: { orgId: "" projectId: "" dimension: MAX_VCPU value: 16 }) { maxVcpu currentVcpu } } } ``` `dimension` is one of `MAX_INSTANCES`, `MAX_VCPU`, `MAX_VOLUME_GIB`, `MAX_VPCS` and `MAX_PUBLIC_IPS`. A negative value, or one above the organization quota, is refused rather than capped. Lowering a budget below current usage doesn’t remove anything; it refuses further growth until usage drops below the budget. ## What a refusal looks like [#what-a-refusal-looks-like] A request that would exceed a quota fails with `BAD_REQUEST` on the field `quota`, and nothing is created. The message names the scope, the dimension, the current usage and the limit: ```text invalid input on field quota: project quota exceeded: vCPU usage is 14, requesting 4 more would exceed the limit of 16 ``` Free up usage, raise or clear the project budget, or ask Origin Cloud support for a higher organization quota. ## Compute [#compute] | Quota | Field | Counts | Checked when you | | --- | --- | --- | --- | | Instances | `maxInstances` | Instances that aren’t terminated | Launch an instance | | vCPU | `maxVcpu` | vCPUs of the instances that count, by instance type | Launch an instance, or change an instance to a larger type | Stopped instances count against both quotas until you terminate them. Changing an instance to a smaller type is never refused by quota. A launch also counts the instance’s root volume against the storage quota and, in a subnet that assigns public IPs, its public address against the public IP quota. For instance type sizes and the root disk size rules, see [Instance types](/docs/compute/instances/instance-types) and [Launch an instance](/docs/compute/instances/launch). ## Storage [#storage] | Quota | Field | Counts | Checked when you | | --- | --- | --- | --- | | Volume storage | `maxVolumeGib` | The size in GiB of all volumes that aren’t deleted | Create or import a volume, grow a volume, or launch an instance | | Snapshots | Not readable | Snapshots | Create a snapshot | A resize counts only the growth, not the volume’s whole new size. The snapshot quota applies per organization. It isn’t returned by `organisationQuota`; the refusal message states the limit. For volume sizes, see [Volumes](/docs/storage/volumes). ## Network [#network] | Quota | Field | Counts | Checked when you | | --- | --- | --- | --- | | VPCs | `maxVpcs` | VPCs, including default VPCs | Create a VPC, or launch the first instance into a project’s default VPC | | Public IPs | `maxPublicIps` | Floating IPs, whether you allocated them or the platform assigned them at launch | Allocate a Floating IP, or launch into a subnet that assigns public IPs | | Subnets | Not readable | Subnets | Create a subnet | | Internet gateways | Not readable | Internet gateways | Attach an internet gateway | | NAT gateways | Not readable | NAT gateways | Create a NAT gateway | | Route tables | Not readable | Route tables | Create a route table | | Network ACLs | Not readable | Network ACLs | Create a network ACL | | Security groups | Not readable | Security groups | Create a security group | | Rules per network ACL | Not readable | Rules in one network ACL | Replace a network ACL’s rules | | Rules per security group | Not readable | Ingress and egress rules of one security group, combined | Replace a security group’s rules | The quotas marked “Not readable” apply per organization and aren’t returned by `organisationQuota`; the refusal message states the limit. The two rule quotas apply to each network ACL or security group separately. If the platform assigns no public address at launch, for example because the public IP quota is used up, the launch still succeeds and the instance runs without one. See [Default VPC](/docs/network/vpcs/default-vpc). For address ranges and subnet sizes, see [VPC and subnet addressing](/docs/network/vpcs/addressing). ## IAM [#iam] IAM has no quotas. The number of members, role assignments and service accounts in an organization isn’t limited. | Limit | Value | | --- | --- | | Audit log entries per page | 100 by default, 500 at most. See [Audit log](/docs/iam/audit-log). | | Org-wide Owners | At least one at all times. The last one can’t be revoked or removed. | ## Organizations and projects [#organizations-and-projects] | Limit | Value | | --- | --- | | Projects per organization | No quota | | Project ID | At most 16 characters, including the prefix you choose | | Support cases per page | 100 by default, 500 at most | ## Related [#related] - [Error codes](/docs/platform/reference/errors) - [Organizations and projects](/docs/platform/organizations) # What is Origin Cloud Pricing? The public price list gives the current list price of every billable product, in euro, over HTTP without an account or token. Origin Cloud publishes the current list price of every billable product in one public price list: instance types, volume storage classes, snapshots, Floating IPs, NAT gateways, network traffic, and observability. You read it over HTTP, without an account or an access token. Use it to estimate costs before you launch anything, or to show current prices on your own website. ## How the price list is organized [#how-the-price-list-is-organized] Your client sends one request, `GET /v1/pricing`, and gets back the price list. The list holds product families, such as `compute_instance` and `storage_volume`, and each family holds the prices of its products, such as `compute.gp1.core.2` or `storage.gp1`. ## Key concepts [#key-concepts] - **List price**: The rate every organization is billed at unless it has agreed a different rate with Origin Cloud. The price list is read from the same price records that invoices are calculated from, so a published price and a billed one can't drift apart. A rate agreed for one organization is never shown in the list. - **Product family**: A group of products that are billed the same way, such as `compute_instance` or `network_vpc_egress`. The list shows the families in a fixed order and leaves out a family that has no current price. See [Product families](/docs/pricing/reference/price-list-api#product-families). - **Product key**: The identifier of what a price bills, for example `compute.gp1.core.2`, `storage.gp1`, or `network.vpc_egress`. Usage and cost reports use the same keys. - **Unit**: Every price is `amount` euro per `unit_count` of `unit_type`. A `unit_count` of 3600 with `unit_type` `seconds` is an hourly rate. Traffic in `gb` is counted in decimal gigabytes (10^9 bytes). All amounts exclude VAT. A product in the price list isn't necessarily available to order. Selecting a product that is priced but not on sale fails with . ## Ways to access Pricing [#ways-to-access-pricing] - **HTTP**: `GET https://api.origincloud.eu/v1/pricing` returns the price list as JSON. See [Read the price list](/docs/pricing/read-price-list) and the [Price list API reference](/docs/pricing/reference/price-list-api). The price list isn't part of the GraphQL API, and the origin CLI doesn't read it. ## Related services [#related-services] - [Billing](/docs/platform/billing): how your organization pays for what it uses. - [Instance types](/docs/compute/instances/instance-types): what each `compute_instance` price buys. - [Storage classes](/docs/storage/volumes/storage-classes): what each `storage_volume` price buys. ## Next steps [#next-steps] - [Read the price list](/docs/pricing/read-price-list) - [Pricing reference](/docs/pricing/reference) # Read the price list Fetch the public price list with curl, revalidate it with a conditional request, and turn a price into an hourly or monthly cost. Fetch the current list prices to estimate what a resource costs, or to show prices on your own site. The price list is public, so you need no account or access token. The examples on this page use the list prices of 13 October 2026. Prices change; fetch the list for current values. ## Before you begin [#before-you-begin] - `curl` to send the requests. - Optional: `jq` to filter the JSON response. ## Fetch the price list [#fetch-the-price-list] 1. Request the price list and include the response headers: ```sh curl -si https://api.origincloud.eu/v1/pricing ``` The example shows one family only. Example output (headers illustrative): ```text HTTP/2 200 content-type: application/json etag: W/"3f9a1c2b7d4e5f60" cache-control: public, max-age=300 access-control-allow-origin: * last-modified: Tue, 22 Sep 2026 19:42:11 GMT {"currency":"EUR","amounts_exclude_vat":true,"last_changed":"2026-09-22T19:42:11.021738+00:00","families":[{"family":"compute_instance","prices":[{"product_key":"compute.gp1.core.2","dimensions":{"instance_type":"gp1.core.2"},"unit_type":"seconds","unit_count":3600,"amount":"0.0551","valid_from":"2026-08-11T08:37:24.666437+00:00","valid_until":null}]}]} ``` 1. Note the `etag` value. You use it in the next section to check for changes without downloading the list again. 1. Optional: list the prices of one family. This command prints each instance type with its price: ```sh curl -s https://api.origincloud.eu/v1/pricing \ | jq -r '.families[] | select(.family == "compute_instance") | .prices[] | "\(.product_key) \(.amount) EUR per \(.unit_count) \(.unit_type)"' ``` Example output (first two lines): ```text compute.gp1.core.2 0.0551 EUR per 3600 seconds compute.gp1.core.4 0.1103 EUR per 3600 seconds ``` If a family you expect is missing, it has no current price. For every field in the response, see [Price list API](/docs/pricing/reference/price-list-api). ## Check for changes with a conditional request [#check-for-changes-with-a-conditional-request] 1. Send the `etag` value from your last response in an `If-None-Match` header: ```sh curl -si https://api.origincloud.eu/v1/pricing \ -H 'If-None-Match: W/"3f9a1c2b7d4e5f60"' ``` 1. Check the status code. `304 Not Modified` with no body means the price list hasn’t changed, and you keep using your copy. `200` returns the new list with a new `etag`. Example output (illustrative): ```text HTTP/2 304 etag: W/"3f9a1c2b7d4e5f60" cache-control: public, max-age=300 access-control-allow-origin: * last-modified: Tue, 22 Sep 2026 19:42:11 GMT ``` You can reuse a fetched list for 5 minutes without asking again, as `cache-control: public, max-age=300` allows. A price change can take a few minutes to appear. ## Calculate a cost from a price [#calculate-a-cost-from-a-price] Every price is `amount` euro per `unit_count` of `unit_type`, without VAT. Divide `amount` by `unit_count` to get the price of one unit, then multiply by the units you use. 1. Calculate an hourly rate for a price in `seconds`. For `compute.gp1.core.2` with `amount` `"0.0551"` and `unit_count` `3600`: ```text 0.0551 / 3600 * 3600 seconds = 0.0551 EUR per hour ``` 1. Calculate a monthly estimate by multiplying the hourly rate by the hours in the month. For 730 hours: ```text 0.0551 EUR per hour * 730 hours = 40.22 EUR ``` 1. Calculate a storage cost for a price in `gib_hours` by multiplying the size by the hours. For `storage.gp1` with `amount` `"0.00009589"` and `unit_count` `1`, a 100 GiB volume kept for 730 hours costs: ```text 0.00009589 / 1 * (100 GiB * 730 hours) = 7.00 EUR ``` 1. Verify the result against your usage and cost reports, which use the same product keys. Read `amount` as a decimal string, not a floating-point number, to avoid rounding errors in your calculation. ## Related [#related] - [Price list API](/docs/pricing/reference/price-list-api) – every field, family, header, and status code. - [Billing](/docs/platform/billing) – how your organization is invoiced. # Pricing reference Reference pages for Pricing, covering the public price list endpoint, its response fields, product families, headers, and status codes. The reference pages describe the public price list in full, so you can look up an exact field, family, or status code. For what list prices are and how to read them, see [What is Origin Cloud Pricing?](/docs/pricing). ## Pages [#pages] | Page | What it lists | | --- | --- | | [Price list API](/docs/pricing/reference/price-list-api) | The `GET /v1/pricing` endpoint: every response field, the product families and their product keys, response headers, and status codes. See [Price list API](/docs/pricing/reference/price-list-api). | ## Related references [#related-references] - [Metrics reference](/docs/observability/reference/metrics) – what the observability families bill for. - [Errors](/docs/platform/reference/errors) – error codes of the GraphQL API, including `PRODUCT_UNAVAILABLE`. # Price list API Reference for GET /v1/pricing, the public price list endpoint, with every response field, product family, header, and status code. The price list endpoint returns the current list price of every billable product as JSON. It needs no authentication. For a walkthrough, see [Read the price list](/docs/pricing/read-price-list). ## Current list prices [#current-list-prices] The table below is read from this endpoint when the page is served. If the endpoint can't be reached, the table shows the copy of 13 October 2026 and says so. Creating a volume with either storage class fails with . See [Storage classes](/docs/storage/volumes/storage-classes). ## Request [#request] ```text GET https://api.origincloud.eu/v1/pricing ``` The endpoint takes no parameters. Optional request header: | Header | Description | | --- | --- | | `If-None-Match` | An ETag from an earlier response. If the price list is unchanged, the response is `304 Not Modified` without a body. A strong form of the same tag, or `*`, also matches. | ## Response body [#response-body] Example response (two families from the price list of 13 October 2026): ```json { "currency": "EUR", "amounts_exclude_vat": true, "last_changed": "2026-09-22T19:42:11.021738+00:00", "families": [ { "family": "compute_instance", "prices": [ { "product_key": "compute.gp1.core.2", "dimensions": { "instance_type": "gp1.core.2" }, "unit_type": "seconds", "unit_count": 3600, "amount": "0.0551", "valid_from": "2026-08-11T08:37:24.666437+00:00", "valid_until": null } ] }, { "family": "storage_snapshot", "prices": [ { "product_key": "storage.snapshot", "unit_type": "gib_hours", "unit_count": 1, "amount": "0.000045644000", "valid_from": "2026-08-18T12:33:38.761168+00:00", "valid_until": null } ] } ] } ``` Top-level fields: | Field | Type | Description | | --- | --- | --- | | `currency` | string | Always `EUR`. | | `amounts_exclude_vat` | boolean | Always `true`. Every amount is net. VAT depends on your billing country and is added on the invoice. | | `last_changed` | string or null | RFC 3339 timestamp of the most recent time a list price was set, changed, took effect, or ended. Use it for a “prices last updated” line. `null` only if nothing has ever been priced. | | `families` | array | One entry per product family with at least one current price, in the order of [Product families](#product-families). A family without a current price is left out. | Fields of each entry in `families`: | Field | Type | Description | | --- | --- | --- | | `family` | string | The family identifier, for example `compute_instance`. | | `prices` | array | The current prices of the family, ordered by product key, with numbers compared as numbers. Instance types of one class run from smallest to largest. | Fields of each entry in `prices`: | Field | Type | Description | | --- | --- | --- | | `product_key` | string | What the price bills, for example `compute.gp1.core.2`. Usage and cost reports use the same key. | | `dimensions` | object | The parts of the product key, already split out: `instance_type` for `compute_instance`, `storage_class` for `storage_volume`. The field is absent when the family has no dimensions. | | `unit_type` | string | The unit the price is per: `seconds`, `gib_hours`, `gb`, `metric_months`, `requests`, or `samples`. | | `unit_count` | integer | How many units `amount` is for. `3600` `seconds` is an hourly rate; `730` `gib_hours` is a rate per GiB for 730 hours. | | `amount` | string | The price in euro for `unit_count` units, as a decimal string so no rounding is introduced. | | `valid_from` | string | RFC 3339 timestamp from which the price applies. | | `valid_until` | string or null | RFC 3339 timestamp at which the price is scheduled to end, or `null` if no end is scheduled. | The list contains only prices in effect at the time of the request. A future price appears once it takes effect. Prices agreed for a single organization never appear. A priced product isn’t necessarily available to order. Selecting a product that is priced but not on sale fails with `PRODUCT_UNAVAILABLE`. ## Product families [#product-families] The families appear in the following order. Traffic in `gb` is counted in decimal gigabytes (10^9 bytes). | Family | Product key | Dimensions | Unit type | | --- | --- | --- | --- | | `compute_instance` | `compute.` | `instance_type` | `seconds` | | `network_floating_ip` | `network.floating_ip` | – | `seconds` | | `network_nat_gateway` | `network.nat_gateway` | – | `seconds` | | `network_vpc_egress` | `network.vpc_egress` | – | `gb` | | `network_vpc_ingress` | `network.vpc_ingress` | – | `gb` | | `network_vpc_internal` | `network.vpc_internal` | – | `gb` | | `storage_volume` | `storage.` | `storage_class` | `gib_hours` | | `storage_snapshot` | `storage.snapshot` | – | `gib_hours` | | `observability_custom_metric` | `observability.custom_metric` | – | `metric_months` | | `observability_api_request` | `observability.api_request` | – | `requests` | | `observability_ingested_sample` | `observability.ingested_sample` | – | `samples` | ### compute_instance [#compute_instance] The time an instance runs, priced per instance type. The product key is `compute.` followed by the instance type, for example `compute.gp1.core.2`. See [Instance types](/docs/compute/instances/instance-types). ### network_floating_ip [#network_floating_ip] The time a Floating IP is allocated to your project. See [Floating IPs](/docs/network/internet-access/floating-ips). ### network_nat_gateway [#network_nat_gateway] The time a NAT gateway exists. The Floating IP that the gateway holds is billed separately under `network_floating_ip`. See [NAT gateways](/docs/network/internet-access/nat-gateways). ### network_vpc_egress [#network_vpc_egress] Traffic from a VPC to the internet, in decimal gigabytes. ### network_vpc_ingress [#network_vpc_ingress] Traffic from the internet into a VPC, in decimal gigabytes. ### network_vpc_internal [#network_vpc_internal] Traffic routed between two subnets of the same VPC, in decimal gigabytes. ### storage_volume [#storage_volume] The provisioned size of a volume for the time it exists, priced per storage class. The product key is `storage.` followed by the storage class: `storage.gp1`, `storage.st1`, or `storage.io1`. See [Storage classes](/docs/storage/volumes/storage-classes). ### storage_snapshot [#storage_snapshot] The size of a snapshot’s source volume for the time the snapshot exists. See [Snapshots](/docs/storage/snapshots). ### observability_custom_metric [#observability_custom_metric] A metric you submit yourself, for each month it’s kept. Submitting your own metrics isn’t supported, so nothing is billed under this family. ### observability_api_request [#observability_api_request] Each successful `observability.metrics` query, however many metrics or data points it returns. See [Query metrics](/docs/observability/query-metrics). ### observability_ingested_sample [#observability_ingested_sample] Each value the platform collects for your instances, volumes, and network interfaces: one per metric and resource every 30 seconds while the instance runs. See [Metrics reference](/docs/observability/reference/metrics). For example, an instance with one network interface and one volume reports five metrics, so 730 hours of running produce 5 × 120 × 730 = 438,000 samples. At the list price of 13 October 2026 (`0.1000` EUR per 1,000,000 samples), that is about 0.04 EUR per instance-month. ## Response headers [#response-headers] | Header | Value | | --- | --- | | `ETag` | A weak tag for the response body, for example `W/"3f9a1c2b7d4e5f60"`. It changes whenever the body changes. | | `Cache-Control` | `public, max-age=300`. A client or cache may reuse a fetched list for 5 minutes. A price change can take a few minutes to appear. | | `Access-Control-Allow-Origin` | `*`. A web page on any origin can fetch the list from the browser. | | `Last-Modified` | The time in `last_changed`, as an HTTP date. Absent when `last_changed` is `null`. | | `Content-Type` | `application/json`, on `200` responses. | In a browser, let the browser’s HTTP cache revalidate the list. The `ETag` header isn’t exposed to page scripts, and a script that sets `If-None-Match` itself triggers a CORS preflight request, which the endpoint doesn’t support. ## Status codes [#status-codes] | Status | Meaning | What to do | | --- | --- | --- | | 200 OK | The body is the current price list. | – | | 304 Not Modified | The `If-None-Match` tag matches the current list. No body. | Keep using your copy. | | 429 Too Many Requests | Too many requests from your client address. The limit is per client address. | Wait and retry. A client that honors `Cache-Control` doesn’t reach the limit. | | 503 Service Unavailable | The price list is temporarily unavailable. The response carries `Retry-After: 30` and a plain-text body. | Retry after the number of seconds in `Retry-After`. | # What is Origin Cloud Storage? Storage gives your instances durable block volumes and point-in-time snapshots. Learn the parts, how they relate to images, and how to access them. Origin Cloud Storage provides durable block volumes for your instances and point-in-time snapshots of those volumes. A volume is a disk that keeps its data independently of any instance. A snapshot captures a volume's data so you can create new volumes or images from it. Most instances get their volumes automatically from their image at launch; this guide covers volumes and snapshots as resources you manage yourself. ## How the parts fit together [#how-the-parts-fit-together] Data moves between volumes, snapshots and images like this: - **Import**: a disk image at a URL becomes a volume. - **Create snapshot**: a volume becomes a snapshot. - **Create volume**: a snapshot becomes a new volume. - **Create image**: a snapshot becomes an image. - **Launch**: an image becomes a new instance's volume. A snapshot becomes usable as a source only after you protect it. For the rules, see [Snapshot states](/docs/storage/snapshots/snapshot-states). ## Features [#features] - **Volumes**: Durable block disks that you create, import, resize, attach to instances, and delete. See [Volumes](/docs/storage/volumes). - **Storage classes**: Performance tiers for volumes. `gp1` (general purpose, SSD-backed) is the tier you can select. See [Storage classes](/docs/storage/volumes/storage-classes). - **Snapshots**: Point-in-time, crash-consistent copies of a volume, used as the source for new volumes and images. See [Snapshots](/docs/storage/snapshots). - **Disk image import**: Create a volume whose initial content is a disk image you download from an HTTP(S) URL. See [Import a disk image as a volume](/docs/storage/volumes/import). ## Ways to access Storage [#ways-to-access-storage] - **origin CLI**: The `origin storage` command group covers volumes, storage classes, and snapshots. See [origin storage commands](/docs/storage/reference/cli). - **GraphQL API**: Volumes, snapshots, and storage classes live under the `pvs` namespace of the API. See [Storage reference](/docs/storage/reference). - **Origin Cloud console**: The web interface at [console.origincloud.eu](https://console.origincloud.eu), for working with your volumes and snapshots in a browser. These docs cover the CLI and the API. For installing the CLI and authenticating, see [Access Origin Cloud](/docs/platform/access). ## Related services [#related-services] - [Instance storage](/docs/compute/instance-storage): how an instance's own volumes are created at launch. - [Attach and detach volumes](/docs/compute/instance-storage/attach-detach): connect a volume you created to an instance. - [Create an image](/docs/compute/images/create): turn a protected snapshot into an image you can launch instances from. - [Pricing](/docs/pricing): how volumes and snapshots are billed. ## Next steps [#next-steps] - [Create a volume](/docs/storage/volumes/create) - [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect) - [Troubleshoot storage](/docs/storage/troubleshooting) # origin storage commands Every origin storage command with its flags: volumes, storage classes, imports and snapshots. This page lists every `origin storage` command. Attaching a volume to an instance is an `origin compute` command; see [`attach-volume`](/docs/compute/reference/cli#attach-volume). ## create-volume [#create-volume] Create a volume, empty or from a snapshot. ```sh origin storage create-volume [OPTIONS] --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--size ` | no | Size in GiB [default: 8]. | | `--snapshot-urn ` | no | URN of the backing Snapshot. | | `--storage-class ` | no | Storage class (performance tier). Omitted uses the platform default. Discover the choices with [`list-storage-classes`](#list-storage-classes) | ## list-storage-classes [#list-storage-classes] List every published storage class (performance tier), with display name, backing media, which one is the default and its `available` flag. Only a class with `available: true` can be passed to `--storage-class`. ```sh origin storage list-storage-classes ``` This command takes no options. ## list-volumes [#list-volumes] List the volumes of a project. ```sh origin storage list-volumes --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-volume [#get-volume] Get one volume. ```sh origin storage get-volume --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--volume-urn ` | yes | URN of the Volume. | ## import-volume [#import-volume] Create a volume whose initial content is a disk image downloaded from an HTTP(S) URL. ```sh origin storage import-volume [OPTIONS] --project-urn --size-in-gib --source-url ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | | `--size-in-gib ` | yes | Size in GiB - must be large enough to hold the source image. | | `--source-url ` | yes | HTTP(S) URL the source image is downloaded from. It must be reachable from the internet. | | `--storage-class ` | no | Storage class (performance tier). Omitted uses the platform default. Discover the choices with [`list-storage-classes`](#list-storage-classes) | ## delete-volume [#delete-volume] Delete a volume. Refused while it is attached or has snapshots. ```sh origin storage delete-volume --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--volume-urn ` | yes | URN of the Volume. | A volume with snapshots may be accepted for deletion and silently stay `AVAILABLE` instead of being refused (seen on 12 October 2026). Check with `get-volume` that `status` reads `DELETED`. See [Delete a volume](/docs/storage/volumes/delete#delete-the-volume). ## resize-volume [#resize-volume] Grow a volume. Volumes only grow. ```sh origin storage resize-volume --volume-urn --size-in-gib ``` | Option | Required | Description | | --- | --- | --- | | `--volume-urn ` | yes | URN of the Volume. | | `--size-in-gib ` | yes | New size in GiB. | ## create-snapshot [#create-snapshot] Take a snapshot of a volume. ```sh origin storage create-snapshot --volume-urn ``` | Option | Required | Description | | --- | --- | --- | | `--volume-urn ` | yes | URN of the Volume. | ## protect-snapshot [#protect-snapshot] Protect a snapshot so it can be used as a clone source. ```sh origin storage protect-snapshot --snapshot-urn ``` | Option | Required | Description | | --- | --- | --- | | `--snapshot-urn ` | yes | URN of the Snapshot. | ## unprotect-snapshot [#unprotect-snapshot] Remove a snapshot’s protection so it can be deleted. ```sh origin storage unprotect-snapshot --snapshot-urn ``` | Option | Required | Description | | --- | --- | --- | | `--snapshot-urn ` | yes | URN of the Snapshot. | ## delete-snapshot [#delete-snapshot] Delete a snapshot. It must be unprotected first. ```sh origin storage delete-snapshot --snapshot-urn ``` | Option | Required | Description | | --- | --- | --- | | `--snapshot-urn ` | yes | URN of the Snapshot. | ## list-snapshots [#list-snapshots] List the snapshots of a project. ```sh origin storage list-snapshots --project-urn ``` | Option | Required | Description | | --- | --- | --- | | `--project-urn ` | yes | URN of the project. | ## get-snapshot [#get-snapshot] Get one snapshot. ```sh origin storage get-snapshot --snapshot-urn ``` | Option | Required | Description | | --- | --- | --- | | `--snapshot-urn ` | yes | URN of the Snapshot. | # Storage reference Look up every origin storage CLI command and every GraphQL query and mutation in the pvs namespace for volumes, snapshots, and storage classes. The storage reference covers the `origin storage` CLI commands and the `pvs` (Persistent Volume Storage) namespace of the GraphQL API. For concepts and procedures, see [Volumes](/docs/storage/volumes) and [Snapshots](/docs/storage/snapshots). ## CLI [#cli] [`origin storage` commands](/docs/storage/reference/cli) lists every command with its options. Attaching and detaching volumes are `origin compute` commands; see [`attach-volume`](/docs/compute/reference/cli#attach-volume) and [`detach-volume`](/docs/compute/reference/cli#detach-volume). ## GraphQL queries [#graphql-queries] Queries live under `query { pvs { … } }`. | Query | Returns | Permission | | --- | --- | --- | | `volumes(input: { projectUrn })` | The project’s volumes, without deleted ones. | `pvs.volume.list` | | `volume(volumeUrn)` | One volume, including a deleted one. | `pvs.volume.get` | | `snapshots(input: { projectUrn })` | The project’s snapshots, without deleted ones. | `pvs.snapshot.list` | | `snapshot(snapshotUrn)` | One snapshot, including a deleted one. | `pvs.snapshot.get` | | `storageClasses` | Every published storage class with its `available` flag. | None | To find the instance an `INUSE` volume is attached to, use the `compute.volumeAttachments` query. See [Find the instance a volume is attached to](/docs/storage/volumes/find-instance). ## GraphQL mutations [#graphql-mutations] Mutations live under `mutation { pvs { … } }`. Mutations that return `CommandRequestStatus` report only that the request was accepted; read the resource to see the result. | Mutation | Effect | Returns | Permission | | --- | --- | --- | --- | | `createVolume` | Creates a volume, empty or from a snapshot. See [Create a volume](/docs/storage/volumes/create). | `PvsVolume` | `pvs.volume.create` | | `importVolume` | Creates a volume from a disk image at a URL. See [Import a disk image as a volume](/docs/storage/volumes/import). | `PvsVolume` | `pvs.volume.create` | | `resizeVolume` | Grows a volume. See [Resize a volume](/docs/storage/volumes/resize). | `CommandRequestStatus` | `pvs.volume.update` | | `deleteVolume` | Deletes a volume. See [Delete a volume](/docs/storage/volumes/delete). | `CommandRequestStatus` | `pvs.volume.delete` | | `createSnapshot` | Takes a snapshot of a volume. See [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect). | `PvsSnapshot` | `pvs.snapshot.create` | | `protectSnapshot` | Protects a snapshot so it can be a clone source. | `CommandRequestStatus` | `pvs.snapshot.protect` | | `unprotectSnapshot` | Lifts a snapshot’s protection. | `CommandRequestStatus` | `pvs.snapshot.unprotect` | | `deleteSnapshot` | Deletes an unprotected snapshot. See [Delete a snapshot](/docs/storage/snapshots/delete). | `CommandRequestStatus` | `pvs.snapshot.delete` | ## Status values [#status-values] The `status`, `modificationStatus`, and `protectionStatus` fields are strings. Their values are listed in [Volume states](/docs/storage/volumes/volume-states) and [Snapshot states](/docs/storage/snapshots/snapshot-states). ## Errors and limits [#errors-and-limits] - [Error codes](/docs/platform/reference/errors) - [Storage limits](/docs/platform/reference/limits#storage) # Create and protect a snapshot Take a crash-consistent snapshot of an available or attached volume, wait for it to complete, and protect it so it can be used as a clone source. Take a snapshot to capture a volume’s data at one point in time. Protect it when you want to create volumes or images from it. You don’t have to detach a volume to snapshot it. ## Before you begin [#before-you-begin] - The volume’s URN. - Permission `pvs.snapshot.create` on the volume, and `pvs.snapshot.protect` on the snapshot. See [Roles](/docs/iam/roles). - A volume that reports `AVAILABLE` or `INUSE`. A volume in `CREATING` is refused, not queued; wait for `AVAILABLE`. A volume in `DELETING`, `DELETED`, or `ERROR` has nothing left to copy. - An active organization and a billing account that can pay. See [Add a payment method](/docs/platform/billing/payment-method). - Room in your snapshot quota. See [Limits](/docs/platform/reference/limits). ## Create the snapshot [#create-the-snapshot] 1. If the volume is attached to a running instance, quiesce the filesystem inside the guest when you need more than crash consistency. The snapshot is taken while the instance runs and captures the disk as a sudden power-off would. 1. Create the snapshot. ```sh origin storage create-snapshot --volume-urn ``` With the API, use the `createSnapshot` mutation: ```graphql mutation { pvs { createSnapshot(input: { volumeUrn: "" }) { urn status } } } ``` The snapshot reports `PENDING`. Note its `urn`. 1. Check the snapshot until it reports `status: COMPLETED`. ```sh origin storage get-snapshot --snapshot-urn ``` If it reports `ERROR`, the copy failed. Delete it and take a new one. ## Protect the snapshot [#protect-the-snapshot] Protect the snapshot only after it reports `COMPLETED`. A protect request for a `PENDING` snapshot is refused, not queued. 1. Protect the snapshot. ```sh origin storage protect-snapshot --snapshot-urn ``` With the API, use the `protectSnapshot` mutation: ```graphql mutation { pvs { protectSnapshot(input: { snapshotUrn: "" }) { accepted message } } } ``` 1. Check the snapshot until it reports `protectionStatus: PROTECTED`. ```sh origin storage get-snapshot --snapshot-urn ``` If it reports `FAILED`, the protection state is unknown. Protect it again. See [Snapshot states](/docs/storage/snapshots/snapshot-states). The snapshot is now a clone source: `status: COMPLETED` and `protectionStatus: PROTECTED`. Keep the snapshot protected for as long as you use anything built on it. The platform doesn’t check whether an image uses the snapshot: once you unprotect or delete it, creating volumes from it and launching instances from an image built on it are refused. See [Delete a snapshot](/docs/storage/snapshots/delete). ## Next steps [#next-steps] - [Create a volume from a snapshot](/docs/storage/volumes/create#create-a-volume-from-a-snapshot) - [Create an image](/docs/compute/images/create) ## Related [#related] - [Snapshot states](/docs/storage/snapshots/snapshot-states) - [`create-snapshot` command](/docs/storage/reference/cli#create-snapshot) - [`protect-snapshot` command](/docs/storage/reference/cli#protect-snapshot) # Delete a snapshot Unprotect a snapshot if needed, delete it, and confirm that it reports DELETED so it no longer blocks deleting its volume. Delete a snapshot when you no longer need it, or to clear the way for deleting the volume it was taken from. A protected snapshot must be unprotected first. ## Before you begin [#before-you-begin] - The snapshot’s URN. - Permission `pvs.snapshot.delete` on the snapshot, and `pvs.snapshot.unprotect` if it’s protected. See [Roles](/docs/iam/roles). - A snapshot that reports `COMPLETED` or `ERROR`. A `PENDING` snapshot can’t be deleted yet; wait until the copy finishes. The platform doesn’t check whether an image uses the snapshot. Once you unprotect or delete a snapshot, creating volumes from it and launching instances from an image built on it are refused. ## Unprotect the snapshot [#unprotect-the-snapshot] Skip this section if the snapshot reports `protectionStatus: UNPROTECTED`. 1. Unprotect the snapshot. This works on a `COMPLETED` snapshot and on an `ERROR` snapshot, and also settles a snapshot whose `protectionStatus` is `FAILED`. ```sh origin storage unprotect-snapshot --snapshot-urn ``` With the API, use the `unprotectSnapshot` mutation: ```graphql mutation { pvs { unprotectSnapshot(input: { snapshotUrn: "" }) { accepted message } } } ``` 1. Check the snapshot until it reports `protectionStatus: UNPROTECTED`. ```sh origin storage get-snapshot --snapshot-urn ``` ## Delete the snapshot [#delete-the-snapshot] 1. Delete the snapshot. ```sh origin storage delete-snapshot --snapshot-urn ``` With the API, use the `deleteSnapshot` mutation: ```graphql mutation { pvs { deleteSnapshot(input: { snapshotUrn: "" }) { accepted message } } } ``` A delete request for a snapshot that isn’t `UNPROTECTED` is refused with the message `snapshot must be unprotected before it can be deleted`. 1. Check the snapshot until it reports `status: DELETED`. ```sh origin storage get-snapshot --snapshot-urn ``` A deleted snapshot drops out of `origin storage list-snapshots` at once. You can still look it up by URN, with no time limit. ## If this fails [#if-this-fails] If the deletion is accepted but fails, the snapshot stays in your list as `ERROR` with a `statusReason`. Its copy may still exist, and it still blocks deleting its volume. Delete it again. If it’s still protected, unprotect it first. ## Next steps [#next-steps] - [Delete a volume](/docs/storage/volumes/delete) ## Related [#related] - [Snapshot states](/docs/storage/snapshots/snapshot-states) - [`unprotect-snapshot` command](/docs/storage/reference/cli#unprotect-snapshot) - [`delete-snapshot` command](/docs/storage/reference/cli#delete-snapshot) # Snapshots A snapshot is a point-in-time copy of a volume. Learn how snapshots connect volumes to new volumes and images, and find the snapshot tasks. A snapshot is a point-in-time copy of a volume’s data. Snapshots let you reuse that data: as the starting point of a new volume, or as the source of an image that you launch instances from. A snapshot depends on its volume’s stored data, so a volume can’t be deleted while any of its snapshots exists. The path from a volume to a usable clone source, and what you can create from it: 1. Create a snapshot of a volume. 1. Protect the snapshot. 1. From the `PROTECTED` snapshot, create a new volume, or create an image and launch instances from it. ## Key concepts [#key-concepts] | Concept | Description | | --- | --- | | Snapshot states | A snapshot reports a `status` for the copy itself and a `protectionStatus`. Only a snapshot that is `COMPLETED` and `PROTECTED` can be used as a clone source. See [Snapshot states](/docs/storage/snapshots/snapshot-states). | | Protection | An explicit step after creation that makes a snapshot usable as a clone source. A protected snapshot can’t be deleted until you unprotect it. See [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect). | | Crash consistency | A snapshot of an attached volume is taken while the instance runs. It captures the disk as a sudden power-off would. | ## What you can do [#what-you-can-do] - [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect) - [Create a volume from a snapshot](/docs/storage/volumes/create#create-a-volume-from-a-snapshot) - [Create an image from a protected snapshot](/docs/compute/images/create) (a compute operation) - [Delete a snapshot](/docs/storage/snapshots/delete) ## Limits and quotas [#limits-and-quotas] The number of snapshots is capped per organization and, where set, per project. Completed snapshots are billed for the size of the volume they were taken from. See [Limits](/docs/platform/reference/limits) and [Pricing](/docs/pricing). The list price of a completed snapshot is €0.000045644 per GiB-hour, about €0.033 per GiB-month at 730 hours (EUR, excluding VAT, as of 2026-10-13). Check the [price list](/docs/pricing/reference/price-list-api#storage_snapshot) for current values. ## Related [#related] - [Volumes](/docs/storage/volumes) - [`origin storage` commands](/docs/storage/reference/cli) - [Troubleshoot storage](/docs/storage/troubleshooting) # Snapshot states The status and protection status values a snapshot reports, what FAILED protection means, and when a snapshot can be used as a clone source. A snapshot reports two independent fields: `status` describes the copy itself, and `protectionStatus` describes whether it’s protected. A snapshot is usable as a clone source only when it reports `status: COMPLETED` and `protectionStatus: PROTECTED`. Creating, protecting, unprotecting, and deleting a snapshot are asynchronous, and these fields tell you how the work ended. ## Status [#status] A new snapshot starts `PENDING` and moves to `COMPLETED` when the copy finishes, or to `ERROR` if creation fails. Deleting a `COMPLETED` or `ERROR` snapshot moves it to `DELETING` and then `DELETED`, or to `ERROR` if deletion fails. | Status | Meaning | Billed | | --- | --- | --- | | `PENDING` | The platform is copying the volume’s data. | No | | `COMPLETED` | The copy is finished. | Yes | | `ERROR` | Creating or deleting the snapshot failed. `statusReason` says what failed. | No | | `DELETING` | The platform is removing the snapshot. | No | | `DELETED` | The snapshot is gone. | No | While a snapshot is `PENDING`, `progress` reports `PENDING` and `percentComplete` shows how far the copy has got. `progress` is `AVAILABLE` once the data is fully copied, and `UNAVAILABLE` when no progress information exists. ## When an operation fails [#when-an-operation-fails] - A snapshot that couldn’t be created ends in `ERROR` instead of `COMPLETED`. There’s no usable snapshot behind it. Delete it and take a new one. - A snapshot that couldn’t be deleted stays in your list as `ERROR` instead of reaching `DELETED`. Its copy may still exist, and it still blocks deleting the volume it was taken from. Delete it again once the cause is resolved. `statusReason` is `null` for every status except `ERROR`. ## Protection status [#protection-status] The `protectionStatus` values are below. A new snapshot starts `UNPROTECTED`. Protecting moves it through `PROTECTING` to `PROTECTED`; unprotecting moves it through `UNPROTECTING` back to `UNPROTECTED`. If either change fails, it ends in `FAILED`, from which you can protect or unprotect it again. | Value | Clone source | Deletable | | --- | --- | --- | | `UNPROTECTED` | No | Yes | | `PROTECTING` | No | No | | `PROTECTED` | Yes, if `COMPLETED` | No | | `UNPROTECTING` | No | No | | `FAILED` | No | No | `FAILED` means the last protect or unprotect couldn’t be applied, so the snapshot’s real protection state is unknown. The platform treats it as neither protected nor unprotected. `protectionStatusReason` says why the change failed, and the snapshot’s data is unaffected. To settle the state, protect the snapshot again, or unprotect it, which is also the way to get it to a state you can delete. Which status a protect or unprotect needs: - Protect needs `status: COMPLETED`. A `PENDING` snapshot has no finished copy yet; a `DELETING`, `DELETED`, or `ERROR` snapshot has nothing to protect. - Unprotect works on a `COMPLETED` snapshot and on an `ERROR` snapshot. Unprotecting an `ERROR` snapshot lets you delete it. Asking for the protection state a snapshot already has succeeds and changes nothing. A refused protect or unprotect changes nothing about the snapshot. ## Clone sources [#clone-sources] A snapshot can be the source of a new volume, an image, or an instance’s volume launched from that image. Every one of those paths checks the same rule at the moment of use: `status: COMPLETED` and `protectionStatus: PROTECTED`. A snapshot that met the rule when an image was created but has since been unprotected or deleted no longer passes it. ## Settled states [#settled-states] A `COMPLETED` snapshot stays usable as a clone source as long as it stays protected, and a `DELETED` snapshot stays gone. A deleted snapshot drops out of your snapshot list immediately. You can still look it up by its URN, with no time limit. ## Related [#related] - [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect) - [Delete a snapshot](/docs/storage/snapshots/delete) - [Volume states](/docs/storage/volumes/volume-states) # Troubleshoot storage Fix common volume and snapshot problems, from volumes in ERROR and failed resizes to refused deletes, failed imports, and refused requests. Each section below describes one symptom, its cause, and how to resolve it. For the error codes the API returns, see [Error codes](/docs/platform/reference/errors). ## Find your symptom [#find-your-symptom] ## Volume reports ERROR after create or import [#volume-reports-error-after-create-or-import] A new volume reports `status: ERROR` instead of `AVAILABLE`, with a `statusReason` of the form `the operation failed ()`. The platform couldn’t provision the volume. There’s no usable disk behind it. - Delete the volume. Deleting an `ERROR` volume is allowed. See [Delete a volume](/docs/storage/volumes/delete). - Create or import the volume again. For import failures, see [Import fails with `ERR_IMPORT` or `ERR_IMPORT_IMAGE_TOO_LARGE`](#import-fails-with-err_import-or-err_import_image_too_large). ## Volume reports ERROR after delete [#volume-reports-error-after-delete] A deleted volume stays in your volume list with `status: ERROR` instead of disappearing. The platform couldn’t remove the volume’s disk. The disk may still exist, so the volume still counts against your quota. - Delete the volume again. - If it returns to `ERROR` again, contact support with the volume’s URN and its `statusReason`. ## Resize reports FAILED [#resize-reports-failed] After a resize, the volume reports `modificationStatus: FAILED` with a `modificationStatusReason`, and `sizeInGib` still shows the old size. The platform accepted the resize but couldn’t apply it. The volume’s data is intact and it’s still usable at its old size. - Request the resize again. See [Resize a volume](/docs/storage/volumes/resize). ## Resize is refused [#resize-is-refused] `resize-volume` fails immediately with an error such as `volumes can only grow, the volume is already GiB`, or `a volume in state cannot be resized`. The requested size isn’t larger than the current size, or the volume isn’t `AVAILABLE` or `INUSE`, or another resize is still in progress. Nothing about the volume changed. - Ask for a size larger than the current `sizeInGib`. Volumes can’t shrink. - Wait for a `CREATING` volume to become `AVAILABLE`, or for `modificationStatus` to leave `RESIZING`, then retry. ## Volume delete is refused because it’s attached [#volume-delete-is-refused-because-its-attached] `delete-volume` fails with `the volume cannot be deleted while an instance attachment still claims it: `. The volume is attached to an instance and reports `INUSE`. - Find the instance. See [Find the instance a volume is attached to](/docs/storage/volumes/find-instance). - Detach the volume. See [Attach and detach volumes](/docs/compute/instance-storage/attach-detach). - Delete the volume again. ## Volume delete is refused because of snapshots [#volume-delete-is-refused-because-of-snapshots] `delete-volume` fails with `the volume cannot be deleted while a snapshot of it still exists: `, or the same message naming several snapshots. A snapshot depends on its volume’s data. Every snapshot that isn’t `DELETED` blocks the delete, including one in `ERROR`. - Delete each named snapshot, unprotecting it first if needed. See [Delete a snapshot](/docs/storage/snapshots/delete). - Wait until each reports `DELETED`. - Delete the volume again. The delete may also be accepted without an error and do nothing (seen on 12 October 2026). If a volume stays `AVAILABLE` after `delete-volume`, find its snapshots with `origin storage list-snapshots --project-urn | jq --arg v "" '.. | objects | select(.volumeUrn? == $v)'` and delete them first. ## Volume still exists after its instance was terminated [#volume-still-exists-after-its-instance-was-terminated] After you terminate an instance, one of its volumes is still `AVAILABLE` and billed, and `retentionNote` is set. The volume couldn’t be deleted with the instance, most often because a snapshot of it exists. The platform keeps the volume instead of deleting your snapshot. - Delete the volume’s snapshots, then the volume. See [Delete a volume](/docs/storage/volumes/delete). ## Snapshot can’t be used as a clone source [#snapshot-cant-be-used-as-a-clone-source] Creating a volume from a snapshot, creating an image, or launching from an image fails with `snapshot is not available` or `snapshot is not protected`. A clone source must report `status: COMPLETED` and `protectionStatus: PROTECTED`. - Wait for a `PENDING` snapshot to reach `COMPLETED`. - Protect the snapshot, or protect it again if `protectionStatus` is `FAILED`. See [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect). If the error says `the size must be greater or equal than used snapshot size`, ask for at least the snapshot’s `volumeSizeInGib`. ## Snapshot delete is refused [#snapshot-delete-is-refused] `delete-snapshot` fails with `snapshot must be unprotected before it can be deleted`. The snapshot is `PROTECTED`, in a protection change, or its `protectionStatus` is `FAILED`. - Unprotect the snapshot and wait for `UNPROTECTED`. See [Delete a snapshot](/docs/storage/snapshots/delete). - Delete it again. ## Import fails with ERR_IMPORT or ERR_IMPORT_IMAGE_TOO_LARGE [#import-fails-with-err_import-or-err_import_image_too_large] An imported volume reports `ERROR` with `statusReason` `the operation failed (ERR_IMPORT_IMAGE_TOO_LARGE)` or `the operation failed (ERR_IMPORT)`. `ERR_IMPORT_IMAGE_TOO_LARGE` means the image’s virtual size is larger than `sizeInGib`. `ERR_IMPORT` means the download, conversion, or write failed: the source returned an HTTP error, sent nothing for 60 seconds, or the import took longer than 25 minutes. - Delete the failed volume. - Import again with `sizeInGib` at least the image’s virtual size, or from a faster or reachable source. See [Import a disk image as a volume](/docs/storage/volumes/import). ## Request refused with PRODUCT_UNAVAILABLE [#request-refused-with-product_unavailable] `create-volume` or `import-volume` fails with `PRODUCT_UNAVAILABLE` and a message such as `storage class 'st1' is not available - use one of: gp1`. The storage class is published but can’t be selected. - Use a class whose `available` is `true`, or omit the class to get `gp1`. See [Storage classes](/docs/storage/volumes/storage-classes). ## Request refused with PAYMENT_METHOD_REQUIRED [#request-refused-with-payment_method_required] Creating, importing, or resizing a volume, or creating a snapshot, fails with `PAYMENT_METHOD_REQUIRED`. The project’s billing account can’t pay. For card-managed billing, no verified payment method is on file. Nothing was created or changed. - Add a payment method. See [Add a payment method](/docs/platform/billing/payment-method). - Retry the request. ## Request refused because a quota is exceeded [#request-refused-because-a-quota-is-exceeded] A create, import, resize, or snapshot request fails with a message such as `organisation quota exceeded: volume storage (GiB) usage is , requesting more would exceed the limit of `. The request would take your organization or project over its volume storage or snapshot quota. Volumes in `CREATING`, `DELETING`, and `ERROR` count too. - Delete volumes or snapshots you no longer need, including ones in `ERROR`. - Retry the request, or ask for a higher limit. See [Limits](/docs/platform/reference/limits). ## Request refused because the organization isn’t active [#request-refused-because-the-organization-isnt-active] A create, import, resize, or snapshot request fails with `organisation is , not active`. Your organization hasn’t been approved yet, or is no longer active. - Check your organization’s status. See [Organization review status](/docs/platform/organizations/review-status). # Create a volume Create an empty volume or a volume from a protected snapshot with the origin CLI or the GraphQL API, and check that it becomes AVAILABLE. Create a standalone volume when you need a disk that isn’t tied to one instance’s lifetime. You can create an empty volume of a given size, or a volume that starts with the data of a snapshot. ## Before you begin [#before-you-begin] - The URN of the project to create the volume in. - Permission `pvs.volume.create` on the project. See [Roles](/docs/iam/roles). - An active organization. See [Organization review status](/docs/platform/organizations/review-status). - A billing account that can pay. For card-managed billing, that means a verified payment method. See [Add a payment method](/docs/platform/billing/payment-method). - Enough volume storage quota for the full size of the new volume. See [Limits](/docs/platform/reference/limits). - To create from a snapshot: a snapshot in the same project that reports `status: COMPLETED` and `protectionStatus: PROTECTED`. See [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect). ## Create an empty volume [#create-an-empty-volume] 1. Optional: list the storage classes and pick one whose `available` is `true`. Omit the class to get the default, `gp1`. See [Storage classes](/docs/storage/volumes/storage-classes). ```sh origin storage list-storage-classes ``` 1. Create the volume. `--size` is in GiB and defaults to 8. ```sh origin storage create-volume --project-urn \ --size 100 --storage-class gp1 ``` With the API, use the `createVolume` mutation: ```graphql mutation { pvs { createVolume(input: { projectUrn: "" sizeInGib: 100 storageClass: "gp1" }) { urn status } } } ``` The new volume reports `CREATING`. Note its `urn`. 1. Check the volume’s status until it reports `AVAILABLE`. ```sh origin storage get-volume --volume-urn ``` ## Create a volume from a snapshot [#create-a-volume-from-a-snapshot] A volume created from a snapshot starts with the data the snapshot captured. The snapshot must belong to the project you create the volume in. A snapshot in another project is refused as not found, even within the same organization. The platform checks three more rules before it creates anything: - The snapshot reports `status: COMPLETED`. - The snapshot reports `protectionStatus: PROTECTED`. - The size you ask for is at least the size of the volume the snapshot was taken from, shown as the snapshot’s `volumeSizeInGib`. A larger size gives you the extra space. If a rule doesn’t hold, the request is refused with an error that names the rule. Nothing is created. 1. Check the snapshot’s `status`, `protectionStatus`, and `volumeSizeInGib`. ```sh origin storage get-snapshot --snapshot-urn ``` 1. Create the volume, passing a size of at least `volumeSizeInGib`. In the CLI, always pass `--size`: its default of 8 GiB is refused for a snapshot of a larger volume. ```sh origin storage create-volume --project-urn \ --snapshot-urn --size 100 ``` With the API, add `snapshotUrn` to the `createVolume` input. 1. Check the volume’s status until it reports `AVAILABLE`. ```sh origin storage get-volume --volume-urn ``` ## If this fails [#if-this-fails] If the volume reports `ERROR` instead of `AVAILABLE`, its creation failed and `statusReason` says why. Delete it and create a new one. For refused requests, such as `PRODUCT_UNAVAILABLE` or a quota error, see [Troubleshoot storage](/docs/storage/troubleshooting). ## Next steps [#next-steps] - [Attach and detach volumes](/docs/compute/instance-storage/attach-detach) – connect the volume to an instance, running or stopped. - [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect) ## Related [#related] - [Volume states](/docs/storage/volumes/volume-states) - [`create-volume` command](/docs/storage/reference/cli#create-volume) # Delete a volume Delete a volume you no longer need, after detaching it and deleting its snapshots, and confirm that it reports DELETED and frees its quota. Delete a volume to remove its data and stop paying for it. Deleting frees the volume’s share of your storage quota once the deletion completes. You can’t undo a delete. ## Before you begin [#before-you-begin] - The volume’s URN. - Permission `pvs.volume.delete` on the volume. See [Built-in roles](/docs/iam/roles). - The volume isn’t attached to an instance. A volume that reports `INUSE` must be detached first. See [Attach and detach volumes](/docs/compute/instance-storage/attach-detach). - The volume has no snapshots left. Every snapshot that doesn’t report `DELETED` blocks the delete, including one in `ERROR`, because a failed snapshot may still hold a copy of the data. ## Clear what blocks the delete [#clear-what-blocks-the-delete] 1. Check the volume’s status. If it’s `INUSE`, find the instance and detach the volume. See [Find the instance a volume is attached to](/docs/storage/volumes/find-instance). ```sh origin storage get-volume --volume-urn ``` 1. Find the volume’s snapshots. Every snapshot reports the volume it was taken from as `volumeUrn`. List your project’s snapshots with the API and look for that URN: ```graphql query { pvs { snapshots(input: { projectUrn: "" }) { urn volumeUrn status protectionStatus } } } ``` 1. Delete each of those snapshots, unprotecting it first if needed, and wait until each reports `DELETED`. See [Delete a snapshot](/docs/storage/snapshots/delete). ## Delete the volume [#delete-the-volume] 1. Delete the volume. ```sh origin storage delete-volume --volume-urn ``` With the API, use the `deleteVolume` mutation: ```graphql mutation { pvs { deleteVolume(input: { volumeUrn: "" }) { accepted message } } } ``` 1. Check the volume until it reports `DELETED`. ```sh origin storage get-volume --volume-urn ``` A deleted volume drops out of `origin storage list-volumes` at once. You can still look it up by URN, with no time limit. A delete of a volume that still has snapshots should be refused with an error. In our testing on 12 October 2026, it was accepted and silently did nothing. Don’t rely on the error: check that the volume’s `status` reads `DELETED`. If it stays `AVAILABLE`, look for snapshots of it: ```sh origin storage list-snapshots --project-urn \ | jq --arg v "" '.. | objects | select(.volumeUrn? == $v)' ``` Delete every snapshot it prints, unprotecting it first if needed, then delete the volume again. ## What the platform refuses [#what-the-platform-refuses] These requests are refused immediately with an error, and nothing about the volume changes: | Request | What happens | | --- | --- | | The volume is attached | The error names the attachment that holds the volume. Detach the volume, or terminate the instance, and try again. | | The volume has snapshots | The error names each snapshot that blocks the delete. Delete those snapshots first, then try again. | | The volume is already being deleted | A volume in `DELETING` or `DELETED` can’t be deleted again. | You can delete a volume in `ERROR`. That’s how you clean up a volume whose creation or deletion failed. ## If this fails [#if-this-fails] If the deletion is accepted but fails, the volume stays in your list as `ERROR` with a `statusReason`, and its disk may still exist. It still counts against your quota. Delete it again. See [Troubleshoot storage](/docs/storage/troubleshooting). ## Related [#related] - [Volume states](/docs/storage/volumes/volume-states) - [`delete-volume` command](/docs/storage/reference/cli#delete-volume) # Find the instance a volume is attached to Follow an INUSE volume's claimRef to its volume attachment and from there to the instance that holds it, with one CLI command or API query. A volume that reports `INUSE` names what holds it in `claimRef`: the id of a volume attachment. Follow that attachment to find the instance, for example before you detach the volume to delete it. ## Before you begin [#before-you-begin] - The volume’s URN and the URN of the project it belongs to. - Permission `compute.instance.list` on the project, the same permission that lets you list the project’s instances. See [Roles](/docs/iam/roles). ## Find the instance [#find-the-instance] 1. Read the volume’s `claimRef`. ```sh origin storage get-volume --volume-urn ``` 1. List the attachments that reference the volume. ```sh origin compute list-volume-attachments \ --project-urn --volume-urn ``` With the API, use the `volumeAttachments` query: ```graphql query { compute { volumeAttachments(input: { projectUrn: "" volumeUrn: "" }) { id instanceUrn deviceName status } } } ``` 1. Take the entry whose `id` equals the volume’s `claimRef`. Its `instanceUrn` is the instance, and `deviceName` is the device name the guest sees. 1. Confirm by reading the instance. Its `volumeAttachments` include the volume. ```sh origin compute get-instance --instance-urn ``` ## Reading the attachment list [#reading-the-attachment-list] Normally the list has one entry, with status `ATTACHED`. Other entries appear while an attach or detach is in progress and after an attach that `FAILED`. An entry with status `RELEASE_ABANDONED` may still hold the volume: the platform has stopped trying to release it. Detached attachments aren’t listed. A volume from another project returns an empty list, exactly like a volume that doesn’t exist. ## Next steps [#next-steps] - [Attach and detach volumes](/docs/compute/instance-storage/attach-detach) - [Delete a volume](/docs/storage/volumes/delete) ## Related [#related] - [`list-volume-attachments` command](/docs/compute/reference/cli#list-volume-attachments) - [Volume states](/docs/storage/volumes/volume-states) # Import a disk image as a volume Create a volume whose initial content is a disk image downloaded from an HTTP(S) URL, size it correctly, and check that the import succeeded. Import a disk image when you’ve built one yourself and want it as a volume’s initial content. The platform downloads the image from an HTTP(S) URL, converts it to raw format, and writes it into a new volume. To launch instances from the result, snapshot and protect the volume, then create an image from the snapshot. ## Before you begin [#before-you-begin] - The URN of the project to create the volume in. - Permission `pvs.volume.create` on the project, the same permission as creating a volume. See [Roles](/docs/iam/roles). - An active organization, a billing account that can pay, and enough volume storage quota for the full size you ask for. See [Create a volume](/docs/storage/volumes/create). - A disk image at an HTTP(S) URL. The platform sends a plain GET request with no credentials, so the URL itself must grant access. - The image’s virtual size. This is the size of the disk the image represents, not the size of the file you download. For a compressed or sparse image the file is much smaller. For a qcow2 image, `qemu-img info` shows it as `virtual size`. ## Choose the image and size [#choose-the-image-and-size] The platform detects the image format and converts it. Common disk image formats are accepted, including qcow2 (also compressed qcow2) and raw. Host the image file itself, not an archive of it such as `.gz` or `.xz`. `sizeInGib` is the size of the volume you get. It’s what the disk becomes, what counts against your quota, and what you’re billed for: - An image whose virtual size is smaller than `sizeInGib` leaves you the extra space. - An image whose virtual size is larger than `sizeInGib` is refused. The import fails and the volume ends in `ERROR`, because the platform can’t shrink your image without destroying part of it. ## Import the image [#import-the-image] 1. Start the import with a size of at least the image’s virtual size. ```sh origin storage import-volume --project-urn \ --size-in-gib 20 \ --source-url https://example.com/images/my-image.qcow2 ``` With the API, use the `importVolume` mutation: ```graphql mutation { pvs { importVolume(input: { projectUrn: "" sizeInGib: 20 sourceUrl: "https://example.com/images/my-image.qcow2" }) { urn status } } } ``` Add `--storage-class` or `storageClass` to choose a class other than the default. See [Storage classes](/docs/storage/volumes/storage-classes). 1. Check the volume’s status until it leaves `CREATING`. ```sh origin storage get-volume --volume-urn ``` `AVAILABLE` means the import succeeded and the volume holds your image. ## Time limits [#time-limits] An import must finish within 25 minutes, including downloading, converting, and writing the image. The import fails with `ERR_IMPORT` when: - it takes longer than 25 minutes, for example a very large image or a slow source, - the source answers with an HTTP error status, - the source sends no data for 60 seconds. ## If the import fails [#if-the-import-fails] A failed import leaves the volume in `ERROR`, and `statusReason` names the cause: | `statusReason` | Cause and fix | | --- | --- | | `the operation failed (ERR_IMPORT_IMAGE_TOO_LARGE)` | The image’s virtual size is larger than `sizeInGib`. Delete the volume and import again with a larger size. | | `the operation failed (ERR_IMPORT)` | The download, conversion, or write failed, or the import ran out of time. Delete the volume and import again, from a faster source if time was the problem. | No data from a failed import is kept, but the `ERROR` volume counts against your quota until you delete it. See [Delete a volume](/docs/storage/volumes/delete). ## Next steps [#next-steps] - [Create and protect a snapshot](/docs/storage/snapshots/create-and-protect) - [Create an image](/docs/compute/images/create) ## Related [#related] - [Volume states](/docs/storage/volumes/volume-states) - [`import-volume` command](/docs/storage/reference/cli#import-volume) # Volumes A volume is a durable block disk for your instances. Learn the key concepts and find the tasks for creating, resizing, and deleting volumes. A volume is a durable block disk. Its data lives in durable storage, not on the machine that runs your instance, so it survives instance stops and host failures. You can create a volume on its own, attach it to an instance, grow it, snapshot it, and delete it when you no longer need it. Every volume you create yourself is a durable volume of this kind. A volume in context, where its content comes from and what it connects to: - Its content comes from one of three sources: you create it as an empty disk, create it from a protected snapshot, or import a disk image at a URL. - Its storage class sets its performance tier. - You attach it to an instance, and you create snapshots from it. ## Key concepts [#key-concepts] | Concept | Description | | --- | --- | | Storage class | The performance tier of a volume. `gp1` is the default and the tier you can select. See [Storage classes](/docs/storage/volumes/storage-classes). | | Volume states | A volume reports a `status` (such as `AVAILABLE` or `INUSE`) and a separate `modificationStatus` for resizes. Volume operations are asynchronous, and failures show up in these fields. See [Volume states](/docs/storage/volumes/volume-states). | | Attachment | While a volume is attached to an instance, it reports `INUSE` and names the attachment in `claimRef`. See [Find the instance a volume is attached to](/docs/storage/volumes/find-instance). | ## What you can do [#what-you-can-do] - [Create a volume](/docs/storage/volumes/create) - [Import a disk image as a volume](/docs/storage/volumes/import) - [Resize a volume](/docs/storage/volumes/resize) - [Find the instance a volume is attached to](/docs/storage/volumes/find-instance) - [Delete a volume](/docs/storage/volumes/delete) - [Attach and detach volumes](/docs/compute/instance-storage/attach-detach) (a compute operation) ## Limits and quotas [#limits-and-quotas] Provisioned volume storage is capped per organization and per project. Creating, importing, and growing a volume all count against the same cap. See [Limits](/docs/platform/reference/limits). ## Related [#related] - [Snapshots](/docs/storage/snapshots) – point-in-time copies of a volume. - [`origin storage` commands](/docs/storage/reference/cli) - [Troubleshoot storage](/docs/storage/troubleshooting) # Resize a volume Grow a volume, including one attached to a running instance, then extend the partition and filesystem inside the guest to use the new space. Grow a volume when it runs out of space. You can grow a volume while it’s attached to a running instance, without a restart. Volumes only grow: there’s no way to make a volume smaller. ## Before you begin [#before-you-begin] - The volume’s URN. - Permission `pvs.volume.update` on the volume. See [Roles](/docs/iam/roles). - A volume that reports `AVAILABLE` or `INUSE`. A volume in `CREATING` can’t be resized yet; wait for `AVAILABLE`. A volume in `DELETING`, `DELETED`, or `ERROR` can’t be resized. - No other resize in progress: `modificationStatus` is `COMPLETED` or `FAILED`. - An active organization and a billing account that can pay. For card-managed billing, that means a verified payment method. See [Add a payment method](/docs/platform/billing/payment-method). - Quota headroom for the growth. Only the growth counts: taking a 100 GiB volume to 120 GiB needs 20 GiB of headroom. See [Limits](/docs/platform/reference/limits). ## Resize the volume [#resize-the-volume] 1. Check the volume’s current `sizeInGib`, `status`, and `modificationStatus`. ```sh origin storage get-volume --volume-urn ``` 1. Request a size larger than the current `sizeInGib`. ```sh origin storage resize-volume --volume-urn \ --size-in-gib 120 ``` With the API, use the `resizeVolume` mutation: ```graphql mutation { pvs { resizeVolume(input: { volumeUrn: "" sizeInGib: 120 }) { accepted message } } } ``` The volume reports `modificationStatus: RESIZING`, and `pendingSizeInGib` shows the target size. 1. Check the volume until `modificationStatus` reports `COMPLETED` and `sizeInGib` shows the new size. ```sh origin storage get-volume --volume-urn ``` ## Use the new space inside the guest [#use-the-new-space-inside-the-guest] The platform grows the block device. It doesn’t change the partition table or the filesystem on it. - On a running instance, the guest sees the larger disk without a restart. Grow the partition and then the filesystem, for example with `growpart` and the filesystem’s own grow command. Many images do this at boot, so a restart also makes the space appear. - On a stopped instance or a detached volume, nothing is needed now. The instance sees the new size the next time it starts. ## What the platform refuses [#what-the-platform-refuses] These requests are refused immediately with an error, and nothing about the volume changes, not even `modificationStatus`: - A size equal to or smaller than the current `sizeInGib`. Shrinking would truncate the filesystem on the disk. To use less storage, create a smaller volume, copy your data across at file level, and delete the old volume. A volume created from a snapshot can’t be smaller than the snapshot’s source volume, so a snapshot doesn’t help here. - A volume in a state other than `AVAILABLE` or `INUSE`. - A resize while another one is in progress. - A resize that would exceed your volume storage quota, from an inactive organization, or from a project whose billing account can’t pay. If your usage is already over a limit, for example because the limit was lowered, no resize brings you back under it. Deleting volumes you no longer need frees quota, and a delete is never held to a quota. ## If this fails [#if-this-fails] If the platform accepts the resize but can’t apply it, `modificationStatus` reports `FAILED` with a `modificationStatusReason`. The volume’s data is intact and `sizeInGib` still reports its real size. Request the resize again. ## Related [#related] - [Volume states](/docs/storage/volumes/volume-states) - [`resize-volume` command](/docs/storage/reference/cli#resize-volume) - [Troubleshoot storage](/docs/storage/troubleshooting) # Storage classes A storage class is a volume's performance tier. Learn which classes exist, which one you can select today, and how to read the catalog. A storage class is the performance tier of a volume, chosen when you create or import it. `gp1` (general purpose, SSD-backed) is the only class you can select, and it’s the class a volume gets when you don’t name one. ## Published classes [#published-classes] The platform publishes three classes. Only those with `available: true` in the catalog can be selected. | Class | Display name | Media | Available | | --- | --- | --- | --- | | `gp1` | General Purpose | SSD | Yes (default) | | `st1` | Throughput Optimized | HDD | No | | `io1` | I/O Intensive | SSD | No | Read the catalog rather than relying on this table. The `pvs.storageClasses` query and the `origin storage list-storage-classes` command return every published class with its display name, backing media, whether it’s the default, and its `available` flag. The catalog is platform-wide and needs no permission. ```graphql query { pvs { storageClasses { storageClass displayName media isDefault available } } } ``` ## Choosing a class [#choosing-a-class] Pass the class identifier as `storageClass` on the `createVolume` or `importVolume` mutation, or as `--storage-class` on `origin storage create-volume` and `origin storage import-volume`. Omit it to get the default. The platform answers two kinds of wrong values differently: | Value | What happens | | --- | --- | | A published class that isn’t available | For example, `st1` or `io1`. The request is refused with [`PRODUCT_UNAVAILABLE`](/docs/platform/reference/errors#product_unavailable), and the message lists the classes you can use. Nothing is created. | | A class that doesn’t exist | For example, a typo such as `gp2`. The request is refused with [`BAD_REQUEST`](/docs/platform/reference/errors#bad_request) and the message `invalid storage_class`. Nothing is created. | ## Existing volumes [#existing-volumes] A volume keeps the class it was created with. A volume that was created in a class that isn’t selectable now keeps working and stays on its own media. The `available` flag only governs new volumes. ## Price [#price] Volumes are billed per GiB of provisioned size per hour. List prices as of 2026-10-13 (EUR, excluding VAT): | Product | List price | About, per month (730 hours) | | --- | --- | --- | | `gp1` volume | €0.00009589 per GiB-hour | €0.07 per GiB, so a 20 GiB volume is about €1.40 | | Snapshot | €0.000045644 per GiB-hour | €0.033 per GiB | The price list also has entries for `st1` and `io1`, which you can’t select today. A completed snapshot is billed for the size of the volume it was taken from. Read the current values from the [price list](/docs/pricing/reference/price-list-api#storage_volume); see [Pricing](/docs/pricing). ## Related [#related] - [Create a volume](/docs/storage/volumes/create) - [Import a disk image as a volume](/docs/storage/volumes/import) - [`list-storage-classes` command](/docs/storage/reference/cli#list-storage-classes) - [Pricing](/docs/pricing) Volume storage classes on origincloud.eu describes what each tier is for. # Volume states The status and modification status values a volume reports, how asynchronous operations and failures show up in them, and which states are billed. A volume reports two independent fields: `status` describes the volume itself, and `modificationStatus` describes the last resize. Creating, importing, resizing, and deleting a volume are asynchronous. The request returns as soon as the platform accepts it, and these fields tell you how the work ended. ## Status [#status] What moves a volume between status values: - Create or import: the volume starts `CREATING`, then becomes `AVAILABLE`, or `ERROR` if creation fails. - Attach and detach: an `AVAILABLE` volume becomes `INUSE` when attached, and `AVAILABLE` again when detached. - Delete: an `AVAILABLE` or `ERROR` volume moves to `DELETING`, then `DELETED`, or to `ERROR` if deletion fails. An `INUSE` volume moves to `DELETING` when its instance is terminated (see below). | Status | Meaning | Billed | Counts against quota | | --- | --- | --- | --- | | `CREATING` | The platform is provisioning the volume. | No | Yes | | `AVAILABLE` | The volume exists and isn’t attached to an instance. | Yes | Yes | | `INUSE` | The volume is attached to an instance. `claimRef` names the attachment. | Yes | Yes | | `DELETING` | The platform is removing the volume. | No | Yes | | `DELETED` | The volume is gone. | No | No | | `ERROR` | Creating or deleting the volume failed. `statusReason` says what failed. | No | Yes | An `INUSE` volume moves to `DELETING` only when the instance it’s attached to is terminated and the volume is set to be deleted with it. A delete you request yourself is refused while the volume is attached. See [Delete a volume](/docs/storage/volumes/delete). To see which instance holds an `INUSE` volume, see [Find the instance a volume is attached to](/docs/storage/volumes/find-instance). ## When an operation fails [#when-an-operation-fails] A failed operation never reports success. The volume tells you what happened: - A volume that couldn’t be created ends in `ERROR` instead of `AVAILABLE`. It has no usable disk behind it. Delete it and create a new one. - A volume that couldn’t be deleted stays in your volume list as `ERROR` instead of reaching `DELETED`. Its disk may still exist, so it still counts against your quota. Delete it again once the cause is resolved. `statusReason` is `null` for every status except `ERROR`. When set, it has the form `the operation failed ()`, for example `the operation failed (ERR_IMPORT)`. For the codes an import can report, see [Import a disk image as a volume](/docs/storage/volumes/import). Requests the platform can tell are invalid up front, such as deleting an attached volume or shrinking a volume, are refused immediately with an error. They never reach `ERROR`, and nothing about the volume changes. ## Modification status [#modification-status] How `modificationStatus` tracks a resize: a resize moves it from `COMPLETED` to `RESIZING`. When the size is applied it returns to `COMPLETED`; if the resize fails it moves to `FAILED`, and another resize moves it to `RESIZING` again. | Value | Meaning | | --- | --- | | `COMPLETED` | No resize is in progress. The last resize, if any, was applied. | | `RESIZING` | A resize is in progress. `pendingSizeInGib` shows the target size. | | `FAILED` | The last resize wasn’t applied. `modificationStatusReason` says why. | | `MODIFYING` | A modification is in progress on a volume that reports no target size. Treat it like `RESIZING`. | `sizeInGib` changes only after the platform confirms the new size, so it’s always a size the disk really has. While a resize runs, compare `sizeInGib` with `pendingSizeInGib` to tell “still in progress” from “didn’t happen”. A failed resize leaves the volume’s data and `sizeInGib` untouched. For details, see [Resize a volume](/docs/storage/volumes/resize). ## Settled states [#settled-states] A state that has settled stays settled. Only something you do next changes it: - A `DELETED` volume never reappears in your list and never returns to `ERROR`. - An `ERROR` volume leaves that state only through another delete. - A `FAILED` resize keeps its `modificationStatusReason` until you request another resize. ## Deleted volumes [#deleted-volumes] A deleted volume drops out of your volume list immediately. You can still look it up by its URN with `origin storage get-volume` or the `pvs.volume` query, with no time limit, and it reports `DELETED`. ## A volume that outlived its instance [#a-volume-that-outlived-its-instance] When you terminate an instance, the volumes created with it are normally deleted too. If one of them can’t be deleted, most often because a snapshot of it still exists, the platform keeps the volume instead of failing the termination. The volume is `AVAILABLE`, it’s yours, and it’s billed. `retentionNote` on the volume explains why it was kept. It’s `null` on every other volume, including volumes you created yourself. To remove a kept volume, delete its snapshots and then the volume. See [Delete a volume](/docs/storage/volumes/delete). ## Related [#related] - [Snapshot states](/docs/storage/snapshots/snapshot-states) - [Troubleshoot storage](/docs/storage/troubleshooting) - [Storage reference](/docs/storage/reference)