# Multi-factor Authentication (MFA) Source: https://www.latitude.sh/docs/account-security/mfa Latitude.sh supports Multi-factor Authentication (MFA) for authenticating using Time-based One-Time Passwords (TOTP). After setting up MFA for your account, a code will be required every time you want to access the dashboard. MFA works when authenticating with email, Google, or Microsoft. When using [passkeys](/docs/account-security/passkeys) or [SAML Single Sign-On (SSO)](/docs/teams/sso), MFA is skipped—even if it's turned on and enforced. ## Setting up MFA ![Setting up Multi-factor Authentication on the Latitude.sh dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/42.Docs25Q4.MFA.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=60c0cd26537ff5d09d8c70ac529a36e4) 1. On the Latitude.sh dashboard, go to your [profile page](https://www.latitude.sh/dashboard/account) and click the Enroll button in the Multi-factor auth section. 2. Scan the QR code with an authentication app such as Google Authenticator or [1Password](https://www.1password.com). 3. Enter the code shown in the authentication app and click Verify. MFA is now fully set up. ## MFA enforcement Account owners can enforce Multi-Factor Authentication (MFA) for all members. Here's how to do it: * Navigate to **Settings** → **Members & access** → **Multi-Factor Auth (MFA)** tab. * Enable the **Enforce Multi-Factor Authentication (MFA)** toggle. Once enabled, every team member will have to set up MFA to access the team. Note: MFA enforcement is not available for teams using SAML Single Sign-On (SSO), as multi-factor authentication is typically handled by the identity provider. # Passkey Authentication Source: https://www.latitude.sh/docs/account-security/passkeys Sign in without passwords using biometrics or security keys. Latitude.sh supports passkey authentication using WebAuthn/FIDO standards. Passkeys provide a faster and more secure way to sign in using your device's biometrics (fingerprint, face recognition) or security keys, eliminating the need for passwords. ## Setting up Passkeys 1. On the Latitude.sh dashboard, go to your [profile page](https://www.latitude.sh/dashboard/account). 2. In the **Passkeys** section, click **Create passkey** to start the passkey creation process. 3. Follow your device's prompts. 4. Once created, you can customize the passkey name for easy identification. 5. Click **Save** to complete the setup. ## Signing in with Passkeys After setting up passkeys, you can use them to log in: 1. Go to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard). 2. Click **Continue with Passkey**. 3. Follow your device's authentication prompts. 4. You'll be automatically signed in to your account. ## Managing Passkeys You can manage your passkeys from your [profile page](https://www.latitude.sh/dashboard/account): * **Rename passkeys**: Click on a passkey display name, edit it and press enter to save. * **Delete passkeys**: Remove passkeys you no longer use by clicking the delete icon. ## Passkeys with SAML SSO If your team uses [SAML Single Sign-On (SSO)](/docs/teams/sso), passkeys are not available. Users cannot create or log in with passkeys and must authenticate through the organization’s SSO provider. ## Troubleshooting If you're having trouble with passkey authentication: * Ensure your browser supports WebAuthn (most modern browsers do). * Check that your device's biometric authentication is properly configured. * Try using a different passkey if you have multiple registered. * Access your account through a different method and set up a new passkey. * Contact support if you're unable to access your account. # Password authentication Source: https://www.latitude.sh/docs/account-security/password Latitude.sh supports password authentication. This authentication method is provided with an additional layer of security and allows fast and secure access to Latitude.sh resources. ## Enabling Password To enable password login, follow these steps: 1. Access your [profile page](https://www.latitude.sh/dashboard/account) on the Latitude.sh dashboard. 2. Create a password if you haven't set one yet. 3. If you already have a password, but password authentication was disabled, toggle on "Enable authentication with password". You'll be able to use the last password set to log in. ## Logging in with Password Once your password is set and authentication is enabled: * Go to the login screen and enter your email. * If password authentication is active, the password field will appear automatically. ## Recovering Your Password If you forget your password, it can be recovered. 1. On the login screen, enter your email. 2. When the password field appears, click "Reset password". 3. Enter the six-digit code sent to your email. 4. You'll be authenticated and redirected to set a new password. ![Password authentication settings](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/41.Docs25Q4.PasswordAuth.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=745a412012b9d460324deb4d6ebd93e4) ## Updating and Disabling Password You can manage your password settings from the profile page: * **To update your password**: enter the current password and set a new one. If [MFA](/docs/account-security/mfa) is enabled, you'll be prompted to verify. * **To disable password authentication**: toggle off "Enable authentication with password". MFA will be required if enabled. Once disabled, password authentication will no longer be available for your account. # Setting up your account Source: https://www.latitude.sh/docs/account-setup/sign-up You need an active account to begin using Latitude.sh. If you don't have one yet, follow these steps: **1. Create your account** Go to the [Latitude.sh sign-up page](https://www.latitude.sh/dashboard/signup) and enter your company email. You can also choose to continue with third-party authentication options like Google, GitHub, or [SAML SSO](/docs/teams/sso). Click **Continue**. **2. Verify your email and complete profile** Enter the six-digit code sent to your email and click **Verify**. Then provide your name, create a password, and click **Continue**. **3. Set up Team and Project** [Create a Team](/docs/teams/create-team) and click **Continue**. Finally, [Create a Project](/docs/projects/create-project). After completing the account setup, you'll be redirected to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard/). > [!NOTE] > > You must fully verify your account to deploy servers and access all platform > features. See the [Account Verification](/docs/account-setup/verify-account) > section for more details. # Verifying your account Source: https://www.latitude.sh/docs/account-setup/verify-account To keep Latitude.sh a secure platform and avoid abuse, functionality is limited until accounts are verified. To validate your account, visit the [verification page](https://www.latitude.sh/dashboard/verify). You'll need to: **1. Add payment method** **Add a valid credit card**: A \$5 temporary hold will be placed on it and released automatically. **2. Choose verification method** Select one of the following verification options: * Verify with [Stripe Identity](https://support.stripe.com/questions/stripe-identity-faq) by uploading a government-issued ID, **or** * Add \$100 in credits, which will be charged to your credit card and added to your account. You can also pay with cryptocurrency. Once your account is validated, all the platform's features will be unlocked. ## Additional security verification You may be asked to complete additional verification, such as verifying your phone number via WhatsApp. In rare cases, accounts require manual review—our team will reach out to complete the process. ## Spending limits after account verification For hourly plans, new accounts start with a \$100 spending limit, which increases to \$500 with consistent payments. For higher limits, [reach out](https://www.latitude.sh/contact) to the sales team. # Assign VLAN Source: https://www.latitude.sh/docs/api-reference/assign-server-virtual-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_networks/assignments # Attach filesystem to server Source: https://www.latitude.sh/docs/api-reference/attach-filesystem https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/filesystems/{filesystem_id}/attach Attaches a running server to the private storage network the filesystem is served on, so it can mount the filesystem. The attach runs asynchronously and is idempotent. # Authentication Source: https://www.latitude.sh/docs/api-reference/authentication Learn how to authenticate your API requests To create an API token, go to the **Settings & Billing → API Keys** page on the [dashboard](https://www.latitude.sh/dashboard). The key is shown to you only when it's created. If you lose it, you'll have to roll the key or create a new one. ## Using your API key When you create your API key, you will see it in the same section of your Dashboard. You can edit the key name, rotate the token, or delete the key entirely from here. To use your API key simply provide it as part of the authorization header when you make a request. Tokens use the bearer authorization header when you make a request. ```curl theme={null} $ curl \ -s https://api.latitude.sh/user/profile \ -H "Authorization: Bearer YOUR_API_KEY_HERE" \ ``` ## Read-only mode Read-only API keys are limited to GET requests. Enable the **Read-only** toggle when creating or editing an API key. ## IP access restrictions You can restrict API key usage to specific IP addresses or CIDR ranges. Requests from IPs not on the allowlist will be rejected. To configure IP restrictions: 1. Enable the **Limited access** toggle when creating or editing an API key 2. Enter one or more IP addresses or CIDR ranges (e.g., `192.168.1.1` or `10.0.0.0/24`) 3. Click **+** to add additional IPs Both IPv4 and IPv6 addresses are supported. Plain IP addresses are automatically converted to CIDR notation (IPv4 gets `/32`, IPv6 gets `/128`). ## API keys should be kept private API keys allow access to your private data in Latitude.sh. They should not be shared outside of your company. We cannot stress enough how important it is for you not to share your API keys with anyone. In case you suspect your API key has been leaked, you can rotate or delete it on the dashboard and this will revoke access to that key. # Create baseline Source: https://www.latitude.sh/docs/api-reference/create-baseline https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /baselines **Preview.** Available to teams with the `baselines_api` feature flag. Create a baseline in the team. A baseline can target all servers, a custom set (when the plan is not yet known), or one or more specific platforms. When it targets platforms, the disk layout is validated by the same rules a deploy applies — against the smallest of the selected platforms — so a baseline that saves here can be dispatched verbatim. # Create an Elastic IP Source: https://www.latitude.sh/docs/api-reference/create-elastic-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /elastic_ips Creates a new Elastic IP and assigns it to the specified server. The IP is provisioned asynchronously—the response will show status `configuring` and the `id` will be `null` until provisioning completes. Currently only IPv4 /32 addresses in routed mode are supported. # Create a BGP session Source: https://www.latitude.sh/docs/api-reference/create-elastic-ip-bgp-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /elastic_ips/{elastic_ip_id}/bgp_sessions Announce an elastic IP from a server over BGP # Create filesystem Source: https://www.latitude.sh/docs/api-reference/create-filesystem https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/filesystems Allows you to add persistent storage to a project. These filesystems can be used to store data across your servers. # Create firewall Source: https://www.latitude.sh/docs/api-reference/create-firewall https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /firewalls Create a firewall # Assign server to firewall Source: https://www.latitude.sh/docs/api-reference/create-firewall-assignment https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /firewalls/{firewall_id}/assignments Assigns a server or a virtual machine to a firewall by its ID. # Create IPMI credentials Source: https://www.latitude.sh/docs/api-reference/create-ipmi-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/remote_access Generates IPMI credentials for a given server. Remote access creates a VPN connection to the internal network of your server so you can connect to its IPMI. You will have to use a VPN client such as https://openvpn.net to connect. See `VPN Sessions` API to create a VPN connection. Related guide: https://docs.latitude.sh/docs/ipmi # Create a managed database Source: https://www.latitude.sh/docs/api-reference/create-managed-database https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /managed_databases # Create project Source: https://www.latitude.sh/docs/api-reference/create-project https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /projects # Create a network Source: https://www.latitude.sh/docs/api-reference/create-public-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /public_networks **Preview.** Available at locations where the `public_network` feature is enabled. Provision a customer network: an IPv4 block of the chosen size plus a paired IPv6 /64. The network is allocated synchronously and returned in the response; billing is settled in the background. # Create server Source: https://www.latitude.sh/docs/api-reference/create-server https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers # Run power action Source: https://www.latitude.sh/docs/api-reference/create-server-action https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/actions Performs an action on a given server: - `power_on` - `power_off` - `reboot` # Create out-of-band connection Source: https://www.latitude.sh/docs/api-reference/create-server-out-of-band https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/out_of_band_connection # Run Server Reinstall Source: https://www.latitude.sh/docs/api-reference/create-server-reinstall https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/reinstall # Create tag Source: https://www.latitude.sh/docs/api-reference/create-tag https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /tags Create a Tag in the team. # Create VM Source: https://www.latitude.sh/docs/api-reference/create-virtual-machine https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machines Creates a new Virtual Machine. # Run VM power action Source: https://www.latitude.sh/docs/api-reference/create-virtual-machine-action https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machines/{virtual_machine_id}/actions Performs a power action on a given virtual machine: - `power_on` - Starts the virtual machine - `power_off` - Stops the virtual machine - `reboot` - Restarts the virtual machine `power_on` is never blocked. A `power_off` or `reboot` returns `409 Conflict` when a backup is in progress for the virtual machine. # Create VLAN Source: https://www.latitude.sh/docs/api-reference/create-virtual-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_networks Creates a new Virtual Network. # Create volume Source: https://www.latitude.sh/docs/api-reference/create-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/volumes Allows you to add persistent storage to a project. These volumes can be used to store data across your servers. # Delete API key Source: https://www.latitude.sh/docs/api-reference/delete-api-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /auth/api_keys/{api_key_id} Delete an existing API Key. Once deleted, the API Key can no longer be used to access the API. # Release an Elastic IP Source: https://www.latitude.sh/docs/api-reference/delete-elastic-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /elastic_ips/{elastic_ip_id} Releases an Elastic IP, returning it to the available pool. The IP will transition to `releasing` status before being fully removed. Only Elastic IPs with status `active` or `error` can be released. # Delete a BGP session Source: https://www.latitude.sh/docs/api-reference/delete-elastic-ip-bgp-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /elastic_ips/{elastic_ip_id}/bgp_sessions/{id} Stop announcing an elastic IP from a server # Delete filesystem Source: https://www.latitude.sh/docs/api-reference/delete-filesystem https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /storage/filesystems/{filesystem_id} Allows you to remove a filesystem from a project. # Delete firewall Source: https://www.latitude.sh/docs/api-reference/delete-firewall https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /firewalls/{firewall_id} # Delete assignment Source: https://www.latitude.sh/docs/api-reference/delete-firewall-assignment https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /firewalls/{firewall_id}/assignments/{assignment_id} Removes a server or a virtual machine from a firewall by its assignment ID. # Delete project Source: https://www.latitude.sh/docs/api-reference/delete-project https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /projects/{project_id} Deletes a project and releases associated resources. Any Elastic IPs assigned to the project are automatically released and returned to the available pool. # Delete Project SSH Key Source: https://www.latitude.sh/docs/api-reference/delete-project-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /projects/{project_id}/ssh_keys/{ssh_key_id} Allow you remove SSH Keys in a project. Remove a SSH Key from the project won't revoke the SSH Keys access for previously deploy and reinstall actions. # Delete Project user data Source: https://www.latitude.sh/docs/api-reference/delete-project-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /projects/{project_id}/user_data/{user_data_id} Allow you remove User Data in a project. # Delete SSH Key Source: https://www.latitude.sh/docs/api-reference/delete-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /ssh_keys/{ssh_key_id} Allows you remove SSH Keys in a project. Remove a SSH Key from the project won't revoke the SSH Keys access for previously deploy and reinstall actions. # Delete access key Source: https://www.latitude.sh/docs/api-reference/delete-storage-access-keys-username https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /storage/access_keys/{username}/{storage_class} Permanently deletes an object storage access key and its associated provider-side credentials. Deletion cannot be undone: it revokes the key's credentials and removes the key from the storage provider. For `standard` (Wasabi) keys, the IAM user is removed from each of the project's bucket policies, all of the user's access keys are revoked, and the IAM user is deleted. For `high_performance` (VAST) keys, the VAST user's S3 keys are revoked, its attached S3 policies are deleted, and the VAST user is removed. # Delete lifecycle rule Source: https://www.latitude.sh/docs/api-reference/delete-storage-bucket-lifecycle-rule https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /storage/buckets/{bucket_id}/lifecycle_rules/{id} Deletes a lifecycle rule from an object storage bucket. # Delete bucket Source: https://www.latitude.sh/docs/api-reference/delete-storage-buckets https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /storage/buckets/{id} Allows you to remove an object storage from a project. # Delete user data Source: https://www.latitude.sh/docs/api-reference/delete-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /user_data/{user_data_id} # Delete VLAN assignment Source: https://www.latitude.sh/docs/api-reference/delete-virtual-networks-assignments https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /virtual_networks/assignments/{assignment_id} Allow you to remove a Virtual Network assignment. # Delete volume Source: https://www.latitude.sh/docs/api-reference/delete-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /storage/volumes/{id} Allows you to remove a volume from a project. # Delete VPN session Source: https://www.latitude.sh/docs/api-reference/delete-vpn-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /vpn_sessions/{vpn_session_id} Deletes an existing VPN Session. # Delete baseline Source: https://www.latitude.sh/docs/api-reference/destroy-baseline https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /baselines/{baseline_id} **Preview.** Available to teams with the `baselines_api` feature flag. Delete a baseline. # Destroy a managed database Source: https://www.latitude.sh/docs/api-reference/destroy-managed-database https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /managed_databases/{id} # Delete a network Source: https://www.latitude.sh/docs/api-reference/destroy-public-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /public_networks/{id} **Preview.** Available at locations where the `public_network` feature is enabled. Delete a customer network. Only allowed while the network has no IPs in use. # Remove server Source: https://www.latitude.sh/docs/api-reference/destroy-server https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /servers/{server_id} # Delete tag Source: https://www.latitude.sh/docs/api-reference/destroy-tag https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /tags/{tag_id} Update a Tag in the team. # Remove a member Source: https://www.latitude.sh/docs/api-reference/destroy-team-member https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /team/members/{user_id} # Destroy VM Source: https://www.latitude.sh/docs/api-reference/destroy-virtual-machine https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /virtual_machines/{virtual_machine_id} Destroys a Virtual Machine. # Delete VLAN Source: https://www.latitude.sh/docs/api-reference/destroy-virtual-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /virtual_networks/{vlan_id} Delete virtual network # Detach filesystem from server Source: https://www.latitude.sh/docs/api-reference/detach-filesystem https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/filesystems/{filesystem_id}/detach Detaches a server from the storage network the filesystem is served on, removing its storage IP and VLAN. The network stays while a volume is still mapped to the server, since volumes use the same network. The detach runs asynchronously: poll GET .../attach for its status. # Encoding Source: https://www.latitude.sh/docs/api-reference/encoding Character encoding and content types Data is encoded as defined by JSON in [RFC4627](http://www.ietf.org/rfc/rfc4627.txt). The default encoding for APIs is UTF-8. Certain characters, such as Emoji may be handled as surrogate unicode pairs (see section '2.5. Strings' of [RFC4627](http://www.ietf.org/rfc/rfc4627.txt)). Some query parameters may need to be [url encoded](https://en.wikipedia.org/wiki/Percent-encoding) when sending - for example, the `email` parameter value used to query users should be encoded. > [!WARNING] > > **HTML Encoding** > > It should be noted that the following identifiers are encoded to protect from potential cross-site scripting attacks: `name`, `user_id`, `company_id` and `email`. As a result you may see these identifiers in their encoded format when you retrieve them via the API. > > Note that the characters we encode are double quote, single quote, ampersand, less than and greater than symbols i.e " ' & \< > ```text HTML Encoding example theme={null} Let's say you have a company name like "BL&T's". Then when you retrieve it from the API it will look like this: "BL&T's" ``` # Error Codes Source: https://www.latitude.sh/docs/api-reference/error-codes Common error codes and their meanings The API may send the following error codes. Other codes may be added in the future. | Code | Description | | - | - | | `BANDWIDTH_ERROR` | Error while loading bandwidth data. Please, try again | | `FORBIDDEN` | The request was forbidden. Check your permissions. | | `UNPROCESSABLE_ENTITY` | Cannot process the request. Check your data. | | `INVALID_INCLUDE` | Cannot include the data you requested. Check your request. | | `INVALID_TOKEN` | The token is invalid. Request a new token. | | `MISSING_ORGANIZATION` | Organization is missing. Please, contact our support. | | `NOT_FOUND` | Generic error when the subject is not found | | `[RESOURCE]_NOT_FOUND` | Error when the \[RESOURCE] is not found | | `POWER_ACTION_ERROR` | Error while performing a power action. Please, contact our support. | | `REINSTALL_SERVER_FAILURE` | Error while trying to reinstall. Please, contact our support. | | `ROLE_UPDATE_ERROR` | Error while trying to update the role. Please, contact our support. | | `SCHEMA_VALIDATION_ERROR` | The data you sent is invalid. Check your params. | | `SERVER_ALREADY_REINSTALLING` | The server you tried to reinstall is already reinstalling. Please wait it to finish. | | `SERVERS_OUT_OF_STOCK` | No servers available in stock for the requested plan and site. Try a different plan or site. | | `SSH_KEY_OWNERSHIP_ERROR` | The ssh key you tried to add does not belong to the project. Check your project's ssh keys. | | `UNAUTHORIZED` | The token is invalid. Request a new token. | | `VPN_SESSION_ALREADY_INITIATED` | The VPN Session was already initiated. Refresh your credentials. | # Error Objects Source: https://www.latitude.sh/docs/api-reference/error-objects Structure of error responses ## Error Objects The API will return an Error List for a failed request, which will contain one or more Error objects. ### Error List Attributes Each error has the following attributes: | Field | Description | | - | - | | `status` | The HTTP status | | `code` | General context about the error. See [Error Codes](#error-codes) | | `title` | Error title | | `detail` | Error detail | | `meta` | Metadata about the error | ### Error List Object ```json theme={null} [ { "status": "404", "code": "not_found", "title": "Error", "detail": "Specified Record Not Found" } ] ``` # Filtering Source: https://www.latitude.sh/docs/api-reference/filtering Filtering resources with query parameters You can filter by most attributes. If an attribute is not supported, the API will not ignore it and will reject the request instead. You can use the following criteria: ### Simple List team members with first\_name "Stark" * `https://api.latitude.sh/team/members?filter[first_name]=stark ` ### Case sensitive List team members with first\_name "Stark" * `https://api.latitude.sh/team/members?filter[first_name][eql]=Stark` ### Prefix List servers where the hostname starts with "web" * `https://api.latitude.sh/servers?filter[hostname][prefix]=web` ### Suffix List servers where the hostname ends with "arm" * `https://api.latitude.sh/servers?filter[hostname][suffix]=arm` ### Contains List projects where the name includes "workloads" * `https://api.latitude.sh/projects?filter[name][match]=workloads` # List firewall assignments Source: https://www.latitude.sh/docs/api-reference/get-all-firewall-assignments https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /firewalls/assignments Returns a list of all servers and virtual machines assigned to a firewall. # List API keys Source: https://www.latitude.sh/docs/api-reference/get-api-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /auth/api_keys Returns a list of all API keys. # List bandwidth plans Source: https://www.latitude.sh/docs/api-reference/get-bandwidth-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/bandwidth Lists all bandwidth plans. # Retrieve baseline Source: https://www.latitude.sh/docs/api-reference/get-baseline https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /baselines/{baseline_id} **Preview.** Available to teams with the `baselines_api` feature flag. Retrieve a single baseline. # List baselines Source: https://www.latitude.sh/docs/api-reference/get-baselines https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /baselines **Preview.** Available to teams with the `baselines_api` feature flag. The shape of this endpoint may change before general availability. List all baselines in the team. A baseline records the configuration you expect your servers to be delivered with — plan, SSH keys, user data, disk layout and BIOS settings. # Retrieve billing usage Source: https://www.latitude.sh/docs/api-reference/get-billing-usage https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /billing/usage Returns the billing usage of a project # Retrieve an Elastic IP Source: https://www.latitude.sh/docs/api-reference/get-elastic-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /elastic_ips/{elastic_ip_id} Returns a single Elastic IP by its ID. # Retrieve a BGP session Source: https://www.latitude.sh/docs/api-reference/get-elastic-ip-bgp-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /elastic_ips/{elastic_ip_id}/bgp_sessions/{id} Retrieve a BGP session announcing an elastic IP # List events Source: https://www.latitude.sh/docs/api-reference/get-events https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /events Lists actions performed by users on your account. # Get filesystem attachment Source: https://www.latitude.sh/docs/api-reference/get-filesystem-attachment https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/filesystems/{filesystem_id}/attach Returns whether a server is attached to the storage network the filesystem is served on. Poll it after attaching: once the status is "attached", configure the returned storage network on the server and mount the filesystem. # Retrieve firewall Source: https://www.latitude.sh/docs/api-reference/get-firewall https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /firewalls/{firewall_id} Returns a single firewall by its ID. # Firewall assignments Source: https://www.latitude.sh/docs/api-reference/get-firewall-assignments https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /firewalls/{firewall_id}/assignments Returns a list of all servers and virtual machines assigned to a particular firewall. # Retrieve an IP Source: https://www.latitude.sh/docs/api-reference/get-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /ips/{ip_id} Retrieve an IP Address # List IPs Source: https://www.latitude.sh/docs/api-reference/get-ips https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /ips List all Management and Additional IP Addresses. • Management IPs are IPs that are used for the management IP of a device. This is a public IP address that a device is born and dies with. It never changes during the lifecycle of the device. • Additional IPs are individual IPs that can be added to a device as an additional IP that can be used. # List LKS plans Source: https://www.latitude.sh/docs/api-reference/get-lks-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/lks Lists bare metal plans available to LKS with per-site capacity for a node pool. `attributes.regions.locations.in_stock_count` gives the number of servers a node pool can get, keyed by site slug. # List managed database plans Source: https://www.latitude.sh/docs/api-reference/get-managed-database-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/managed_databases # Retrieve a marketplace app Source: https://www.latitude.sh/docs/api-reference/get-marketplace-app https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /marketplace_apps/{id} Retrieve a single marketplace app by ID or slug. Only published apps are visible. # Retrieve plan Source: https://www.latitude.sh/docs/api-reference/get-plan https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/{plan_id} # List plans Source: https://www.latitude.sh/docs/api-reference/get-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans Lists all plans. Availability by region is included in `attributes.regions.locations.available[*]` node for a given plan. # List operating systems Source: https://www.latitude.sh/docs/api-reference/get-plans-operating-system https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/operating_systems Lists all operating systems available to deploy and reinstall. # Retrieve project Source: https://www.latitude.sh/docs/api-reference/get-project https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects/{project_id} Returns a single project belonging to the current team # Retrieve Project SSH Key Source: https://www.latitude.sh/docs/api-reference/get-project-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects/{project_id}/ssh_keys/{ssh_key_id} List all SSH Keys in the project. These keys can be used to access servers after deploy and reinstall actions. # List SSH Keys Source: https://www.latitude.sh/docs/api-reference/get-project-ssh-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects/{project_id}/ssh_keys List all SSH Keys in the project. These keys can be used to access servers after deploy and reinstall actions. # Retrieve Project user data Source: https://www.latitude.sh/docs/api-reference/get-project-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects/{project_id}/user_data/{user_data_id} Get User Data in the project. These scripts can be used to configure servers with user data. # List Project user data Source: https://www.latitude.sh/docs/api-reference/get-project-users-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects/{project_id}/user_data List all Users Data in the project. These scripts can be used to configure servers with user data. # List projects Source: https://www.latitude.sh/docs/api-reference/get-projects https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /projects Returns a list of all projects for the current team # Retrieve a network Source: https://www.latitude.sh/docs/api-reference/get-public-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /public_networks/{id} Retrieve a customer network # List networks Source: https://www.latitude.sh/docs/api-reference/get-public-networks https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /public_networks **Preview.** Available at locations where the `public_network` feature is enabled. List the customer networks owned by the team # Retrieve region Source: https://www.latitude.sh/docs/api-reference/get-region https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /regions/{region_id} # List regions Source: https://www.latitude.sh/docs/api-reference/get-regions https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /regions Lists all [available locations](https://latitude.sh/locations). For server availability by location, please see the [Plans API](/reference/get-plans). # Retrieve role Source: https://www.latitude.sh/docs/api-reference/get-role-id https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /roles/{role_id} # List roles Source: https://www.latitude.sh/docs/api-reference/get-roles https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /roles Returns a list of all roles that can be assigned to users # Retrieve server Source: https://www.latitude.sh/docs/api-reference/get-server https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /servers/{server_id} Returns a server that belongs to the team. # Retrieve deploy config Source: https://www.latitude.sh/docs/api-reference/get-server-deploy-config https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /servers/{server_id}/deploy_config # List out-of-band connections Source: https://www.latitude.sh/docs/api-reference/get-server-out-of-band https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /servers/{server_id}/out_of_band_connection # List servers Source: https://www.latitude.sh/docs/api-reference/get-servers https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /servers Returns a list of all servers belonging to the team. # Retrieve SSH Key Source: https://www.latitude.sh/docs/api-reference/get-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /ssh_keys/{ssh_key_id} List all SSH Keys in the project. These keys can be used to access servers after deploy and reinstall actions. # List SSH Keys Source: https://www.latitude.sh/docs/api-reference/get-ssh-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /ssh_keys List all SSH Keys in the project. These keys can be used to access servers after deploy and reinstall actions. # List access keys Source: https://www.latitude.sh/docs/api-reference/get-storage-access-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/access_keys Lists object storage access keys for a project, grouped by storage class. Secrets are never returned by this endpoint. # Retrieve bucket Source: https://www.latitude.sh/docs/api-reference/get-storage-bucket https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets/{id} Shows details of a specific object storage. # List bucket access keys Source: https://www.latitude.sh/docs/api-reference/get-storage-bucket-access-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets/{id}/access_keys Lists IAM access keys associated with an object storage bucket. Secrets are never returned by this endpoint. # Retrieve lifecycle rule Source: https://www.latitude.sh/docs/api-reference/get-storage-bucket-lifecycle-rule https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets/{bucket_id}/lifecycle_rules/{id} Retrieves details of a specific lifecycle rule. # List lifecycle rules Source: https://www.latitude.sh/docs/api-reference/get-storage-bucket-lifecycle-rules https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets/{bucket_id}/lifecycle_rules Lists all lifecycle rules for a specific object storage bucket. # Retrieve bucket metrics Source: https://www.latitude.sh/docs/api-reference/get-storage-bucket-metrics https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets/{bucket_id}/metrics Retrieves usage metrics for a specific object storage bucket, including storage consumption and estimated cost for the current billing period. # List buckets Source: https://www.latitude.sh/docs/api-reference/get-storage-buckets https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/buckets Lists all object storages from a team. # List storage plans Source: https://www.latitude.sh/docs/api-reference/get-storage-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/storage # List storage usage Source: https://www.latitude.sh/docs/api-reference/get-storage-usage https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/usage Returns daily object storage usage for a project. Each row reports the canonical usage in bytes for a single storage on a given day, plus the provider-reported raw value. # List tags Source: https://www.latitude.sh/docs/api-reference/get-tags https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /tags List all Tags in the team. # Retrieve team Source: https://www.latitude.sh/docs/api-reference/get-team https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /team # List members Source: https://www.latitude.sh/docs/api-reference/get-team-members https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /team/members # Retrieve traffic Source: https://www.latitude.sh/docs/api-reference/get-traffic-consumption https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /traffic # Retrieve traffic quota Source: https://www.latitude.sh/docs/api-reference/get-traffic-quota https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /traffic/quota # Retrieve user data Source: https://www.latitude.sh/docs/api-reference/get-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /user_data/{user_data_id} Get User Data in the project. These scripts can be used to configure servers with user data. # Retrieve profile Source: https://www.latitude.sh/docs/api-reference/get-user-profile https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /user/profile Retrieve the current user profile # List user teams Source: https://www.latitude.sh/docs/api-reference/get-user-teams https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /user/teams Returns a list of all teams the user belongs to # List user data Source: https://www.latitude.sh/docs/api-reference/get-users-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /user_data List all Users Data in the project. These scripts can be used to configure servers with user data. # Retrieve VLAN Source: https://www.latitude.sh/docs/api-reference/get-virtual-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_networks/{vlan_id} Retrieve a Virtual Network. # List VLANs Source: https://www.latitude.sh/docs/api-reference/get-virtual-networks https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_networks Lists virtual networks assigned to a project # List VLAN assignments Source: https://www.latitude.sh/docs/api-reference/get-virtual-networks-assignments https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_networks/assignments Returns a list of all servers assigned to virtual networks. # List VM plans Source: https://www.latitude.sh/docs/api-reference/get-vm-plans https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /plans/virtual_machines # List VPN sessions Source: https://www.latitude.sh/docs/api-reference/get-vpn-sessions https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /vpn_sessions # HTTP Responses Source: https://www.latitude.sh/docs/api-reference/http-responses HTTP status codes used by the API The API returns HTTP responses on each request to indicate the success or otherwise of API requests. The codes listed below are often used, and the API may use others. Note that 4xx and 5xx responses may be returned for any request and clients should cater for them. | Response Code | Description | | - | - | | `200` | Ok -- The request was successful. | | `201` | Created -- The request was successful. | | `400` | Bad Request -- General client error, possibly malformed data. | | `401` | Unauthorized -- The API Key was not authorised (or no API Key was found). | | `403` | Forbidden -- The request is not allowed. | | `404` | Not Found -- The resource was not found. | | `422` | Unprocessable Entity -- The data was well-formed but invalid. | | `429` | Too Many Requests -- The client has reached or exceeded a rate limit, or the server is overloaded. | | `500` | Server Error - Something went wrong on our end. This response is most likely a momentary operational error (e.g. temporary unavailability), and, as a result, requests should be retried once. | # Identifiers and URLs Source: https://www.latitude.sh/docs/api-reference/identifiers-and-urls Resource identifiers and URL conventions All objects in the API have an `id` field indicating their logical identifier. | Parameter | Description | | - | - | | `id` | A string that identifies the object within the API. The `id` field will not be larger than 128 characters (in SQL it corresponds to a `varchar(128)`). | The `id` field is always defined by the API server and is guaranteed to be unique relative to the `type` field - this means no two user objects will have the same `id` field, but a user and a company may have the same value for their `id` fields. # List VMs Source: https://www.latitude.sh/docs/api-reference/index-virtual-machine https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines Show all Team's Virtual Machines. # Create a Kubernetes Cluster Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/create-a-kubernetes-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /kubernetes_clusters Creates a new managed Kubernetes cluster. Maximum of 1 cluster per project. **Note:** Only users with the `owner`, `administrator`, or `collaborator` role can create clusters. Users with the `billing` role cannot perform this action. Cluster names must follow Kubernetes naming rules: lowercase alphanumeric characters or hyphens, must start and end with an alphanumeric character, and be at most 63 characters long. # Delete a Kubernetes Cluster Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/delete-a-kubernetes-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /kubernetes_clusters/{kubernetes_cluster_id} Deletes a Kubernetes cluster. This action is irreversible and will destroy all cluster resources. **Note:** Only users with the `owner`, `administrator`, or `collaborator` role can delete clusters. Users with the `billing` role cannot perform this action. # Get a Kubernetes Cluster Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/get-a-kubernetes-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /kubernetes_clusters/{kubernetes_cluster_id} Retrieves detailed information about a Kubernetes cluster including its status, control plane, worker node details, and individual node information. # Get Kubernetes Cluster Kubeconfig Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/get-kubernetes-cluster-kubeconfig https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /kubernetes_clusters/{kubernetes_cluster_id}/kubeconfig Retrieves the kubeconfig file for a Kubernetes cluster. The kubeconfig is only available once the cluster is fully provisioned. **Note:** Only users with the `owner`, `administrator`, or `collaborator` role can access cluster credentials. Users with the `billing` role cannot perform this action. # List Available Kubernetes Versions Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/list-available-kubernetes-versions https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /kubernetes_clusters/available_versions Returns the list of available Kubernetes versions for cluster creation and upgrades. Versions are sourced from the RKE2 release channels and cached for 24 hours. Each version object includes: - `latest`: The full version string (e.g., `v1.35.3+rke2r1`) - `minor`: The minor version number (e.g., `1.35`) The API returns the latest 5 supported minor versions. When upgrading clusters, you can only upgrade one minor version at a time (e.g., from 1.34 to 1.35). # List Kubernetes Clusters Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/list-kubernetes-clusters https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /kubernetes_clusters Lists all Kubernetes clusters for a project. # Update Kubernetes Cluster Source: https://www.latitude.sh/docs/api-reference/kubernetes-clusters/update-kubernetes-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /kubernetes_clusters/{kubernetes_cluster_id} Updates a Kubernetes cluster by scaling nodes or upgrading the Kubernetes version. The cluster must be in `Provisioned` phase to accept updates. ## Scaling Operations Exactly one of `worker_count` or `control_plane_count` must be provided per request. You cannot scale workers and control plane nodes in the same request. When scaling up, the API validates that sufficient server stock is available for the requested delta (e.g., scaling from 2 to 5 workers checks for 3 available servers). When scaling from 0 workers, you must provide a `worker_plan` since there is no existing configuration to inherit the plan from. Control plane scaling has a minimum of 1 node. You cannot scale control plane nodes to zero. ## Version Upgrades Provide a `kubernetes_version` parameter to upgrade the cluster to a new Kubernetes version. Version upgrades follow these rules: - **No downgrades**: You cannot downgrade to a lower version than currently installed - **One minor version at a time**: You can only upgrade one minor version at a time (e.g., from 1.34 to 1.35, not from 1.34 to 1.36) - **Mutually exclusive**: Version upgrades cannot be combined with scaling operations in the same request - **Available versions only**: The target version must be in the list returned by `GET /kubernetes_clusters/available_versions` Returns 202 Accepted when an update operation is triggered. Poll the GET endpoint to monitor progress. Returns 200 OK if no change is needed (no-op). # List BGP sessions Source: https://www.latitude.sh/docs/api-reference/list-elastic-ip-bgp-sessions https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /elastic_ips/{elastic_ip_id}/bgp_sessions List the BGP sessions announcing an elastic IP # List Elastic IPs Source: https://www.latitude.sh/docs/api-reference/list-elastic-ips https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /elastic_ips List all Elastic IPs for the authenticated team. Elastic IPs are static public IP addresses that can be assigned to servers and moved between servers within the same project. # List filesystems Source: https://www.latitude.sh/docs/api-reference/list-filesystems https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/filesystems Lists all the filesystems from a team. # List firewalls Source: https://www.latitude.sh/docs/api-reference/list-firewalls https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /firewalls List firewalls # List managed database backups Source: https://www.latitude.sh/docs/api-reference/list-managed-database-backups https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /managed_databases/{managed_database_id}/backups # List managed databases Source: https://www.latitude.sh/docs/api-reference/list-managed-databases https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /managed_databases # List marketplace apps Source: https://www.latitude.sh/docs/api-reference/list-marketplace-apps https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /marketplace_apps Lists the marketplace apps available to deploy on Virtual Machines. Only published apps are returned. # List volumes Source: https://www.latitude.sh/docs/api-reference/list-volumes https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/volumes Lists all the volumes from a team. # Create a node pool Source: https://www.latitude.sh/docs/api-reference/lks/create-a-node-pool https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /lks/clusters/{cluster_id}/nodepools Adds a node pool to an LKS cluster. `mode` decides where the pool's nodes come from: - `on_demand` (default): the platform provisions `count` servers of `plan` from stock, so both fields are required. - `allocated`: the pool is built from `server_ids`, bare metal servers already in the cluster project. Each server is reinstalled with the LKS node image, which erases its disks. `plan` and `count` are rejected: the pool uses the plan the servers share, and `count` is the number of servers. Each server that fails an eligibility check is reported as its own 422 error, pointing at its index in `server_ids` and listing every reason in `meta.reasons`. `GET /lks/allocatable_servers` shows which servers can join. Allocated node pools are available only in on-demand projects: a reserved project is refused with 422 `RESERVED_PROJECT_NOT_SUPPORTED`. `kubernetes_version` defaults to the control-plane patch and may never be newer than it. `max_pods_per_node` and `mode` are set once, here — they cannot be changed later. # Create an LKS cluster Source: https://www.latitude.sh/docs/api-reference/lks/create-an-lks-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /lks/clusters Creates an LKS cluster. The cluster is the control plane only — worker capacity is added separately through node pools (`POST /lks/clusters/{cluster_id}/nodepools`). `site` must be one of the slugs returned by `GET /lks/sites`, and `kubernetes_version` must be a patch listed by `GET /lks/available_versions` with `available_for_creation: true`. The cluster is returned immediately with `status: "provisioning"`. Poll `GET /lks/clusters/{id}` until `status` is `ready`, then fetch the kubeconfig. # Delete a node pool Source: https://www.latitude.sh/docs/api-reference/lks/delete-a-node-pool https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /lks/clusters/{cluster_id}/nodepools/{id} Marks the node pool for deletion. The call returns as soon as the tombstone is written; the platform then drains and releases the nodes asynchronously. # Delete an LKS cluster Source: https://www.latitude.sh/docs/api-reference/lks/delete-an-lks-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /lks/clusters/{id} Marks the cluster for deletion. The call returns as soon as the tombstone is written; the platform then tears the cluster and its node pools down asynchronously. A cluster that is already deleted, or that is paused, rejects the request. # Get a node pool Source: https://www.latitude.sh/docs/api-reference/lks/get-a-node-pool https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters/{cluster_id}/nodepools/{id} Retrieves a single node pool of an LKS cluster. `ready_nodes` reports how many of the pool's `count` nodes have joined the cluster. # Get an LKS cluster Source: https://www.latitude.sh/docs/api-reference/lks/get-an-lks-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters/{id} Retrieves a single LKS cluster. `status` is an open enum sourced from the platform controller — `provisioning`, `ready`, `updating`, `scaling`, `upgrading`, `paused`, `deleting` and `deleted` are the values in use today, and new ones may appear without notice. `reason` and `message` carry the machine-readable and human-readable detail behind the current `status`. # Get the cluster kubeconfig Source: https://www.latitude.sh/docs/api-reference/lks/get-the-cluster-kubeconfig https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters/{id}/kubeconfig Returns the kubeconfig for the cluster. It only exists once the control plane is up, so this endpoint answers 409 `NOT_READY` while the cluster is still provisioning — poll `GET /lks/clusters/{id}` until `kubeconfig_url` is set. # List available Kubernetes versions Source: https://www.latitude.sh/docs/api-reference/lks/list-available-kubernetes-versions https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/available_versions Lists the Kubernetes patches the platform offers, with their lifecycle flags. Use a version with `available_for_creation: true` when creating a cluster or a node pool, and one with `available_for_upgrade: true` when upgrading. Exactly one entry has `default: true`. # List LKS clusters Source: https://www.latitude.sh/docs/api-reference/lks/list-lks-clusters https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters Lists every LKS cluster of a project. The response is not paginated; `meta.total` is the number of clusters returned. # List node pools Source: https://www.latitude.sh/docs/api-reference/lks/list-node-pools https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters/{cluster_id}/nodepools Lists every node pool of an LKS cluster. The response is not paginated; `meta.total` is the number of node pools returned. # List nodes Source: https://www.latitude.sh/docs/api-reference/lks/list-nodes https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/clusters/{cluster_id}/nodepools/{node_pool_id}/nodes Lists the nodes of a node pool, with the status of each node and of the server it runs on. Each node's `id` is a stable node ID (format: `lksno_`); `name` is its Kubernetes node name, as shown by `kubectl get nodes`. The response is not paginated; `meta.total` is the number of nodes returned. # List servers that can join an allocated node pool Source: https://www.latitude.sh/docs/api-reference/lks/list-servers-that-can-join-an-allocated-node-pool https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/allocatable_servers Lists a project's servers at a site, with whether each one can join an allocated node pool right now. Pass the `id` of an allocatable server in `server_ids` when creating or updating an allocated node pool. When `allocatable` is false, `reasons` lists why, using the same codes that node pool create and update return per server. `node_pool_id` and `cluster_id` identify the pool a server already belongs to. # List sites available for LKS Source: https://www.latitude.sh/docs/api-reference/lks/list-sites-available-for-lks https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /lks/sites Lists the sites that can host an LKS cluster, one entry per site. Pass an entry's `id` (the site slug) as `site` when creating a cluster. `country` is null when the underlying site has no region assigned. # Update a node pool Source: https://www.latitude.sh/docs/api-reference/lks/update-a-node-pool https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /lks/clusters/{cluster_id}/nodepools/{id} Scales, renames, upgrades, re-labels or changes the servers of a node pool. At least one attribute must be provided. `labels` and `taints` are declarative replacements, not merges: omit the field to leave it untouched, send the whole map/list to replace it, or send `{}` / `[]` to clear it. A newer `kubernetes_version` rolls a node-recreating upgrade; it must not be lower than the pool's current patch nor newer than the control-plane patch. `max_pods_per_node` and `mode` are immutable — a PATCH that carries either is rejected with 422 even if the value is unchanged. For an allocated node pool, `server_ids` replaces `count`: send the whole set of servers the pool should have. Added servers are checked as on create and reinstalled to join; removed servers are drained and reinstalled with a clean OS, with no data, keys or user data restored. A server set change cannot be combined with a `kubernetes_version` change. The node pool must be idle: one that is provisioning, updating, scaling, upgrading, paused or deleting rejects the request with 409. # Update an LKS cluster Source: https://www.latitude.sh/docs/api-reference/lks/update-an-lks-cluster https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /lks/clusters/{id} Renames a cluster, edits its description, or upgrades the control plane. At least one of `name`, `description` or `kubernetes_version` must be provided. Setting a newer `kubernetes_version` consents to a control-plane upgrade; the value must be a patch listed by `GET /lks/available_versions` with `available_for_upgrade: true` and must not be lower than the current one. Node pools are upgraded separately and must never run a patch newer than the control plane. The cluster must be idle: a cluster that is provisioning, updating, scaling, upgrading, paused or deleting rejects the request with 409. # Show managed database metrics Source: https://www.latitude.sh/docs/api-reference/managed-databases/show-managed-database-metrics https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /managed_databases/{managed_database_id}/metrics # Map volume Source: https://www.latitude.sh/docs/api-reference/map-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/volumes/{id}/map Maps a high performance volume to a server over NVMe-TCP. # Instance Metadata Service Source: https://www.latitude.sh/docs/api-reference/metadata-service Complete reference for the instance metadata service available from within Latitude.sh bare metal servers The instance metadata service is a link-local HTTP API available from within any running Latitude.sh bare metal server. It allows your server to query its own metadata — hostname, IP addresses, network configuration, storage layout, tags, and more — without needing external API credentials. > [!WARNING] > > The instance metadata service is **not** part of the main [Latitude.sh REST API](/docs/api-reference/summary). It uses its own token-based authentication and is only accessible from within a bare metal server. Your regular API keys will not work with this service. > [!WARNING] > > The metadata service is not yet available in the **SAO** and **SAN3** regions. Support for these regions will be added in a future update. ## Base URL All requests use the following base URL: ``` http://169.254.169.254/metadata/v1 ``` This is a link-local address that is only reachable from within the server itself. It is not accessible from the public internet. ## Authentication The metadata service uses token-based authentication (IMDSv2-style). Before making any metadata requests, you must obtain a session token. ### Requesting a token Make a `PUT` request to the token endpoint with a TTL (time-to-live) header specifying how long the token should be valid, in seconds. **Response body:** The session token is returned as plain text in the response body. | Header | Description | | :- | :- | | `X-Metadata-Token` | The session token to use in subsequent requests. | ```bash theme={null} TOKEN=$(curl -s -X PUT "http://169.254.169.254/metadata/v1/api/token" \ -H "X-Metadata-Token-TTL-Seconds: 3600") ``` Use the returned token in the `X-Metadata-Token` header for all subsequent metadata requests. ## Retrieving metadata (full JSON) To retrieve all metadata as a single JSON object, send a `GET` request to `/metadata/v1/metadata.json`: ```bash theme={null} curl -s "http://169.254.169.254/metadata/v1/metadata.json" \ -H "X-Metadata-Token: $TOKEN" | jq ``` **Example response:** ```json theme={null} { "instance_id": "sv_abc123def456", "hostname": "my-server", "local_ipv4": "10.0.0.5", "public_ipv4": "203.0.113.10", "public_ipv6": "2001:db8::1", "region": "SAO", "plan": "c3.medium.x86", "operating_system": "ubuntu_24_04_x64_lts", "userdata": "#cloud-config\npackages:\n - nginx", "tags": [ { "key": "env", "value": "production" }, { "key": "team", "value": "infra" } ], "network": { "interfaces": [ { "name": "eth0", "mac": "aa:bb:cc:dd:ee:f0", "addresses": [ { "address": "203.0.113.10", "prefix": 30, "family": "IPv4", "type": "public" }, { "address": "2001:db8::1", "prefix": 127, "family": "IPv6", "type": "public" } ] }, { "name": "eth1", "mac": "aa:bb:cc:dd:ee:f1", "addresses": [ { "address": "10.0.0.5", "prefix": 24, "family": "IPv4", "type": "private" } ] } ], "dns": { "nameservers": ["8.8.8.8", "8.8.4.4"] } }, "storage": { "disks": [ { "name": "sda", "size_gb": 480, "type": "SSD", "model": "INTEL SSDSC2KB48" }, { "name": "sdb", "size_gb": 480, "type": "SSD", "model": "INTEL SSDSC2KB48" } ] }, "ssh_keys": [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@example.com" ], "vendor": { "latitude": { "project_id": "prj_abc123", "team_id": "team_xyz789" } } } ``` ## Retrieving metadata (path-based) You can query individual metadata fields by appending the field path to the base URL. Each path returns a plain-text value or a JSON fragment. ### Available paths | Path | Description | | :- | :- | | `/metadata/v1/instance_id` | Unique server identifier | | `/metadata/v1/hostname` | Server hostname | | `/metadata/v1/local_ipv4` | Private IPv4 address | | `/metadata/v1/public_ipv4` | Public IPv4 address | | `/metadata/v1/public_ipv6` | Public IPv6 address | | `/metadata/v1/region` | Region code (e.g., `SAO`, `DAL`) | | `/metadata/v1/plan` | Server plan slug | | `/metadata/v1/operating_system` | Operating system slug | | `/metadata/v1/userdata` | User data script content | | `/metadata/v1/tags` | Tags array (JSON) | | `/metadata/v1/network` | Full network configuration (JSON) | | `/metadata/v1/storage` | Storage/disk information (JSON) | | `/metadata/v1/ssh_keys` | SSH public keys (JSON array) | | `/metadata/v1/vendor` | Vendor-specific metadata (JSON) | ### Examples Get the server hostname: ```bash theme={null} curl -s "http://169.254.169.254/metadata/v1/hostname" \ -H "X-Metadata-Token: $TOKEN" ``` ``` my-server ``` Get the public IPv4 address: ```bash theme={null} curl -s "http://169.254.169.254/metadata/v1/public_ipv4" \ -H "X-Metadata-Token: $TOKEN" ``` ``` 203.0.113.10 ``` Get the network configuration: ```bash theme={null} curl -s "http://169.254.169.254/metadata/v1/network" \ -H "X-Metadata-Token: $TOKEN" | jq ``` ## Response schema ### Top-level fields | Field | Type | Description | | :- | :- | :- | | `instance_id` | string | Unique identifier for the server | | `hostname` | string | Server hostname | | `local_ipv4` | string | Private IPv4 address | | `public_ipv4` | string | Public IPv4 address | | `public_ipv6` | string | Public IPv6 address | | `region` | string | Region code where the server is deployed | | `plan` | string | Server plan slug (e.g., `c3.medium.x86`) | | `operating_system` | string | OS slug (e.g., `ubuntu_24_04_x64_lts`) | | `userdata` | string | User data script content, if set during deployment | | `tags` | array | Array of tag objects with `key` and `value` strings | | `network` | object | Network configuration (see below) | | `storage` | object | Storage/disk information (see below) | | `ssh_keys` | array | Array of SSH public key strings | | `vendor` | object | Vendor-specific metadata (see below) | ### `network` object The `network` object contains the server's network interfaces and DNS configuration. **`network.interfaces[]`** | Field | Type | Description | | :- | :- | :- | | `name` | string | Interface name (e.g., `eth0`) | | `mac` | string | MAC address | | `addresses` | array | Array of address objects | **`network.interfaces[].addresses[]`** | Field | Type | Description | | :- | :- | :- | | `address` | string | IP address | | `prefix` | integer | CIDR prefix length | | `family` | string | `IPv4` or `IPv6` | | `type` | string | `public` or `private` | **`network.dns`** | Field | Type | Description | | :- | :- | :- | | `nameservers` | array | Array of DNS nameserver IP addresses | ### `storage` object **`storage.disks[]`** | Field | Type | Description | | :- | :- | :- | | `name` | string | Device name (e.g., `sda`) | | `size_gb` | integer | Disk size in gigabytes | | `type` | string | Disk type (e.g., `SSD`, `NVMe`, `HDD`) | | `model` | string | Disk model identifier | ### `vendor` object **`vendor.latitude`** | Field | Type | Description | | :- | :- | :- | | `project_id` | string | ID of the project this server belongs to | | `team_id` | string | ID of the team that owns the server | > [!TIP] > > You can use the metadata service together with [user data](/docs/servers/user-data) to automatically configure your servers at boot — for example, setting up network interfaces or registering the server in a service discovery system. # Mount volume (deprecated) Source: https://www.latitude.sh/docs/api-reference/mount-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/volumes/{id}/mount Mounts a volume by adding the client to an allowed list # Object Model Source: https://www.latitude.sh/docs/api-reference/object-model Understanding the JSON:API object model ## Common Fields API objects have a `type` field indicating their object type. Each object in the API may be given an identifier, indicated via its `id` field, and will typically be addressable via a URI. Many objects will also have a `created_at` field indicating the object's creation date. ## Dates and Timestamps All temporal fields in the API are encoded as ISO 8601 and are by definition always treated as UTC. The most common time fields are `created_at` and `updated_at`. | Parameter | Description | | - | - | | `created_at` | The time the object was created. In most, but not all cases, this is the time the object was created according to the API server. | | `updated_at` | The time the object was last updated according to the API server. | ### Optional Fields Unpopulated optional data is returned as follows * Number, String, and Boolean types may be returned as having `null` values. * Arrays and Objects may be returned as empty (`[]` `{}`) In general, clients should be able to handle null and empty fields. ### Metadata Some object types have a `meta` field that allows clients to get more info about an object. # Pagination Source: https://www.latitude.sh/docs/api-reference/pagination Paginating through list endpoints By default, the page size is `20` and the page number `1`. This can however be changed by including the `page[size]` and `page[number]` query parameters E.g. 10 per page, second page ```curl theme={null} curl --request GET \ --url 'https://api.latitude.sh/servers?page[size]=10&page[number]=2' \ --header 'Authorization: Bearer API_KEY' \ ``` # Update team Source: https://www.latitude.sh/docs/api-reference/patch-current-team https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /team/{team_id} # Update lifecycle rule Source: https://www.latitude.sh/docs/api-reference/patch-storage-bucket-lifecycle-rule https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /storage/buckets/{bucket_id}/lifecycle_rules/{id} Updates an existing lifecycle rule for an object storage bucket. # Update user data Source: https://www.latitude.sh/docs/api-reference/patch-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /user_data/{user_data_id} Allow you update User Data in a team. # Update profile Source: https://www.latitude.sh/docs/api-reference/patch-user-profile https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /user/profile/{id} Update the current user profile # Create API key Source: https://www.latitude.sh/docs/api-reference/post-api-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /auth/api_keys Create a new API Key that is tied to the current user account. The created API key is only listed ONCE upon creation. It can however be regenerated or deleted. # Create SSH Key Source: https://www.latitude.sh/docs/api-reference/post-project-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /projects/{project_id}/ssh_keys Allow you create SSH Keys in a project. These keys can be used to access servers after deploy and reinstall actions. # Create Project user data Source: https://www.latitude.sh/docs/api-reference/post-project-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /projects/{project_id}/user_data Allows you to create User Data in a project, which can be used to perform custom setup on your servers after deploy and reinstall. # Create SSH Key Source: https://www.latitude.sh/docs/api-reference/post-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /ssh_keys Allows you create SSH Keys. These keys can be used to access servers after deploy and reinstall actions. # Create access key Source: https://www.latitude.sh/docs/api-reference/post-storage-access-keys https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/access_keys Creates an object storage IAM access key for a project. The secret is returned only once, in this response, and cannot be retrieved again. The provider is selected by `storage_class`: `standard` provisions the key on Wasabi and `high_performance` provisions it on VAST. # Create lifecycle rule Source: https://www.latitude.sh/docs/api-reference/post-storage-bucket-lifecycle-rules https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/buckets/{bucket_id}/lifecycle_rules Creates a new lifecycle rule for an object storage bucket. Lifecycle rules automate object expiration based on age. # Create bucket Source: https://www.latitude.sh/docs/api-reference/post-storage-buckets https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/buckets Creates a new object storage bucket for a project. # Create team Source: https://www.latitude.sh/docs/api-reference/post-team https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /team # Create member Source: https://www.latitude.sh/docs/api-reference/post-team-members https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /team/members # Create user data Source: https://www.latitude.sh/docs/api-reference/post-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /user_data Allows you to create User Data in a team, which can be used to perform custom setup on your servers after deploy and reinstall. # Create VPN session Source: https://www.latitude.sh/docs/api-reference/post-vpn-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /vpn_sessions Creates a new VPN Session. `NOTE:` The VPN credentials are only listed ONCE upon creation. They can however be refreshed or deleted. # Update Project SSH Key Source: https://www.latitude.sh/docs/api-reference/put-project-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /projects/{project_id}/ssh_keys/{ssh_key_id} Allow you update SSH Key in a project. These keys can be used to access servers after deploy and reinstall actions. # Update Project user data Source: https://www.latitude.sh/docs/api-reference/put-project-user-data https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /projects/{project_id}/user_data/{user_data_id} Allow you update User Data in a project. # Update SSH Key Source: https://www.latitude.sh/docs/api-reference/put-ssh-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /ssh_keys/{ssh_key_id} Allows you update SSH Key in a project. These keys can be used to access servers after deploy and reinstall actions. # Refresh VPN session Source: https://www.latitude.sh/docs/api-reference/put-vpn-session https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /vpn_sessions/{vpn_session_id}/refresh_password Refreshing an existing VPN Session will create new credentials for that session # Rate Limits Source: https://www.latitude.sh/docs/api-reference/rate-limits API rate limits and how they work The API enforces rate limits per API key. ## Current limits | Request type | Limit | | - | - | | Read (GET requests) | 800 requests per minute | | Write (POST, PUT, PATCH, DELETE requests) | 120 requests per minute | ## Rate limit responses When you exceed the rate limit, the API returns a `429 Too Many Requests` response: ```json theme={null} { "errors": [{ "code": "RATE_LIMIT_EXCEEDED", "title": "Rate Limit Exceeded", "status": "429", "detail": "Too many requests. Please slow down and retry.", "meta": { "retry_after": 60 } }] } ``` The `meta.retry_after` field indicates how many seconds to wait before retrying your request. # Retrieve volume Source: https://www.latitude.sh/docs/api-reference/retrieve-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /storage/volumes/{id} Shows details of a specific volume. # Rotate API key Source: https://www.latitude.sh/docs/api-reference/rotate-api-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples put /auth/api_keys/{api_key_id} Rotate an existing API Key, generating a new token. This invalidates the previous key. Use PATCH to update settings without rotating the token. # Exits rescue mode Source: https://www.latitude.sh/docs/api-reference/server-exit-rescue-mode https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/exit_rescue_mode Exits rescue mode on a given server. # Lock server Source: https://www.latitude.sh/docs/api-reference/server-lock https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/lock Locks the server. A locked server cannot be deleted or modified and no actions can be performed on it. # Schedule server deletion Source: https://www.latitude.sh/docs/api-reference/server-schedule-deletion https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/schedule_deletion Schedules the server to be removed at the end of the billing cycle. # Put server in rescue mode Source: https://www.latitude.sh/docs/api-reference/server-start-rescue-mode https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/rescue_mode Starts rescue mode on a given server. # Unlock server Source: https://www.latitude.sh/docs/api-reference/server-unlock https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /servers/{server_id}/unlock Unlocks the server. A locked server cannot be deleted or modified and no actions can be performed on it. # Unschedule server deletion Source: https://www.latitude.sh/docs/api-reference/server-unschedule-deletion https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /servers/{server_id}/schedule_deletion Unschedules the server removal at the end of the billing cycle. # Show a managed database Source: https://www.latitude.sh/docs/api-reference/show-managed-database https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /managed_databases/{id} # Retrieve VM Source: https://www.latitude.sh/docs/api-reference/show-virtual-machine https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines/{virtual_machine_id} Show a Virtual Machine. # Retrieve VM metrics Source: https://www.latitude.sh/docs/api-reference/show-virtual-machine-metrics https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines/{virtual_machine_id}/metrics Retrieve a time series for a single metric of a Virtual Machine. # Sorting Source: https://www.latitude.sh/docs/api-reference/sorting Sorting results in list endpoints You can sort by most attributes in ascending or descending order. If an attribute is not supported, the API will not ignore it and will reject the request instead. Here's an example of how to list projects sorted by name * *Ascending* `https://api.latitude.sh/projects?sort=name` * *Descending* `https://api.latitude.sh/projects?sort=-name` # Sparse Fieldsets Source: https://www.latitude.sh/docs/api-reference/sparse-fieldsets Requesting specific fields to reduce payload size You can render a selected list of attributes via the `fields[resource_type]=attribute_name` query parameter. Here is an example request to render a list of servers with only the hostname and label of each record. ```curl theme={null} curl --request GET \ --url 'https://api.latitude.sh/servers?fields[servers]=hostname,label' \ ``` # Statistics Source: https://www.latitude.sh/docs/api-reference/statistics Understanding statistics in API responses The following stats are supported: * `stats[total]=count` - The total count of all available records; outside of pagination. Combine with filters and the count will adjust accordingly. The stats are rendered in the `meta` section of the response. ```json theme={null} { "meta": { "stats": { "total": { "count": 2 } } } } ``` # Summary Source: https://www.latitude.sh/docs/api-reference/summary Overview of the Latitude.sh API The Latitude.sh API gives you programmatic access to all resources available on the platform. With full control over the entire Latitude.sh platform, you can build integrations, custom dashboards, and manage your servers from your own clients. The API aims to be flexible and performant every step of the way. The Latitude.sh API has built-in Filtering and Sorting capabilities so you can easily make sense of your infrastructure. For more information about Latitude.sh products, please visit the [product documentation](https://www.latitude.sh/docs) page ### JSON:API The API conforms with the [JSON:API](https://jsonapi.org) specification. As JSON:API is a shared convention, you can take advantage of [generalized tooling](https://jsonapi.org/implementations/), and focus on what matters: your application. ### Credits for public integrations We are confident you will enjoy working with the Latitude.sh API. If you are building a public integration, reach out to [engineering@latitude.sh](mailto:engineering@latitude.sh), and we will be happy to provide you with test and production credits. # Unmap volume Source: https://www.latitude.sh/docs/api-reference/unmap-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /storage/volumes/{id}/unmap Unmaps a high performance volume from the server it is currently mapped to. # Update API key settings Source: https://www.latitude.sh/docs/api-reference/update-api-key https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /auth/api_keys/{api_key_id} Update API Key settings (name, read_only, allowed_ips) without rotating the token. Use PUT to rotate the token. # Move an Elastic IP Source: https://www.latitude.sh/docs/api-reference/update-elastic-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /elastic_ips/{elastic_ip_id} Moves an Elastic IP to a different server within the same project and site. The reassignment is performed asynchronously. The Elastic IP must be in `active` status, the target server must belong to the same project, and the target server must be in the same site as the currently assigned server. # Update filesystem Source: https://www.latitude.sh/docs/api-reference/update-filesystem https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /storage/filesystems/{filesystem_id} Allow you to upgrade the size of a filesystem. # Update firewall Source: https://www.latitude.sh/docs/api-reference/update-firewall https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /firewalls/{firewall_id} Updates a firewall by its ID. # Update a managed database Source: https://www.latitude.sh/docs/api-reference/update-managed-database https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /managed_databases/{id} # Update bandwidth packages Source: https://www.latitude.sh/docs/api-reference/update-plans-bandwidth https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /plans/bandwidth Allows to increase or decrease bandwidth packages. Only admins and owners can request. # Update project Source: https://www.latitude.sh/docs/api-reference/update-project https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /projects/{project_id} # Update a network IP Source: https://www.latitude.sh/docs/api-reference/update-public-network-ip https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /public_networks/{id}/ips **Preview.** Available at locations where the `public_network` feature is enabled. Reserve an available address of a network for your own use, so servers are never attached to the network with it, or release an address you reserved. # Update server Source: https://www.latitude.sh/docs/api-reference/update-server https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /servers/{server_id} # Update deploy config Source: https://www.latitude.sh/docs/api-reference/update-server-deploy-config https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /servers/{server_id}/deploy_config # Update tag Source: https://www.latitude.sh/docs/api-reference/update-tag https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /tags/{tag_id} Update a Tag in the team. # Update VM Source: https://www.latitude.sh/docs/api-reference/update-virtual-machine https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /virtual_machines/{virtual_machine_id} Updates a Virtual Machine's display name (hostname). # Update VLAN Source: https://www.latitude.sh/docs/api-reference/update-virtual-network https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /virtual_networks/{vlan_id} Update a Virtual Network. # Update volume Source: https://www.latitude.sh/docs/api-reference/update-volume https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples patch /storage/volumes/{id} Increases the size of a high performance volume. Shrinking is not supported. Billing is prorated to the new size. # Use of HTTP Source: https://www.latitude.sh/docs/api-reference/use-of-http HTTP methods, status codes, and headers Request methods are used in accordance with HTTP * GET is used to access resources and perform queries. The API does not allow modifications (creates, updates, deletes) to occur via GET. * POST is used to create resources. The preferred model for creation is to post JSON to a 'collections' resource - for example the collections resource for team members is `https://api.latitude.sh/team/members`. * PATCH is used to update resources. * DELETE is used to delete resources. Responses use standard HTTP codes. Where there are client or server errors, a list of of one or more errors in JSON format is returned in the body - see "[Errors](#error-objects)" for more details. The API may send cache directives where suitable, notably the `ETag`, `Last-Modified` and `If-Modified-Since` headers. The `Accept` header must be used by a client used to indicate a preferred response for `GET/HEAD` requests. Requests without an `Accept` header of `application/json` may be rejected with a client error of 404 or 406. The `Content-Type` header should be used by clients to indicate the submitted format for `POST/PUT` requests. # Versioning Source: https://www.latitude.sh/docs/api-reference/versioning API versioning strategy and best practices Tokens are associated with a user and team, and so are API versions. When you update the API with a token you own, it changes the version of all API keys that belong to you. We call this *membership versioning*. All requests use the API version set for your *membership* unless you override it. ### Available versions You can find all available versions by clicking on the dropdown on the left-hand side of this page. When sending the version to an endpoint or overriding the current version, only use the date section. E.g., *v2023-06-01* should be referenced as *2023-06-01*. ### Overriding the current version You can override the version you are using by setting the `API-Version` header on your request. This allows you to use a particular API version for a single endpoint rather than for all requests. **Example**: To send a request for version 2022-07-18, set the`API-Version: 2022-07-18` header. ### Upgrading to a new version You can upgrade and downgrade versions using the Regenerate an API Key endpoint. Generally, we recommend only upgrading to stable versions as we often change beta versions considerably during development. If you want to use beta versions, we recommend doing it on a per-request basis. # Create VM backup Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/create-vm-backup https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machines/{virtual_machine_id}/backups Triggers a backup of the given Virtual Machine. # Create VM backup (top-level) Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/create-vm-backup-top-level https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machine_backups Triggers a backup of the Virtual Machine referenced in the body. # Delete VM backup Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/delete-vm-backup https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /virtual_machine_backups/{id} Archives and deletes a Virtual Machine backup. Work runs asynchronously and returns 202 Accepted. Only `Ready` or `Failed` backups can be deleted, and not while a restore from the backup is in progress. # Get VM backup Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/get-vm-backup https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machine_backups/{id} # List a VM's backups Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/list-a-vms-backups https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines/{virtual_machine_id}/backups Lists the backups of the given Virtual Machine. # List all VM backups Source: https://www.latitude.sh/docs/api-reference/virtual-machine-backups/list-all-vm-backups https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machine_backups Lists every backup that belongs to the authenticated team. # Create VM restore Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/create-vm-restore https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machines/{virtual_machine_id}/backups/{backup_id}/restores Restores a backup into a new Virtual Machine. Optionally accepts a `name` for the restored VM and a target `site` slug to restore into another region. # Create VM restore (flat) Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/create-vm-restore-flat https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machine_restores Restores the backup referenced in the body into a new Virtual Machine. Optionally accepts a `name` for the restored VM and a target `site` slug to restore into another region. # Get VM restore Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/get-vm-restore https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machine_restores/{id} # List a backup's restores Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/list-a-backups-restores https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines/{virtual_machine_id}/backups/{backup_id}/restores Lists the restores created from the given backup. # List a backup's restores (top-level backup path) Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/list-a-backups-restores-top-level-backup-path https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machine_backups/{backup_id}/restores Lists the restores created from the given backup, reached via the top-level backup path. # List all VM restores Source: https://www.latitude.sh/docs/api-reference/virtual-machine-restores/list-all-vm-restores https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machine_restores Lists every restore that belongs to the authenticated team. # Attach a network to a VM Source: https://www.latitude.sh/docs/api-reference/virtual-machines/attach-a-network-to-a-vm https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples post /virtual_machines/{virtual_machine_id}/network_attachments Attaches a virtual network (VLAN) to a Virtual Machine. Work runs asynchronously and returns 202 Accepted. A running VM restarts so the new NIC reaches the guest; a VM that is not running picks it up when it next starts. After the restart, check the interface inside the guest (`ip -br addr`): - VMs created with `apply_network_on_boot` enabled (the default) configure the NIC on boot, with the attachment's `address` when one was given. Nothing else to do. - VMs created before that option existed, or with it disabled, leave the NIC without an address. Once the VM has restarted, read the attachment's `mac_address` and `address` from `GET /virtual_machines/{virtual_machine_id}/network_attachments` and configure the interface with that MAC address yourself, as described in [Private networks: configure the OS](https://www.latitude.sh/docs/networking/private-networks#step-3-configure-the-os). The NIC gets a new MAC address each time a network is attached, so update your configuration after detaching and attaching a network again. Keep network configuration of your own in a separate file. With `apply_network_on_boot`, every boot, including a restart started inside the guest, rewrites cloud-init's own network file (for example `/etc/netplan/50-cloud-init.yaml`), so changes made there are lost. To stop that on a VM, create `/etc/cloud/cloud.cfg.d/99-disable-network-config.cfg` containing `network: {config: disabled}`; cloud-init then leaves the network configuration alone on every boot, and networks attached afterwards must be configured by hand. Some virtual machines run on older infrastructure that doesn't support network attachments. On those VMs, attaching or detaching a network returns 422 `VIRTUAL_NETWORK_ATTACHMENT_UNSUPPORTED` and leaves the VM unchanged. # Detach a network from a VM Source: https://www.latitude.sh/docs/api-reference/virtual-machines/detach-a-network-from-a-vm https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples delete /virtual_machines/{virtual_machine_id}/network_attachments/{id} Detaches a virtual network (VLAN) from a Virtual Machine. Work runs asynchronously and returns 202 Accepted. A running VM restarts so the NIC is removed from the guest; a VM that is not running loses it when it next starts. On VMs created with `apply_network_on_boot` enabled, that boot also removes the NIC's configuration. If you configured the NIC yourself, remove that configuration before detaching, as described in [Private networks: configure the OS](https://www.latitude.sh/docs/networking/private-networks#step-3-configure-the-os). Some virtual machines run on older infrastructure that doesn't support network attachments. On those VMs, attaching or detaching a network returns 422 `VIRTUAL_NETWORK_ATTACHMENT_UNSUPPORTED` and leaves the VM unchanged. # List VM network attachments Source: https://www.latitude.sh/docs/api-reference/virtual-machines/list-vm-network-attachments https://spec.speakeasy.com/latitude/latitude/latitude-sh-api-with-code-samples get /virtual_machines/{virtual_machine_id}/network_attachments Lists the secondary network attachments currently configured for a Virtual Machine. # Changing the billing method Source: https://www.latitude.sh/docs/billing/change-billing-method Upgrade a server or virtual machine to monthly or yearly billing. You can move a server or virtual machine to a longer billing method after it's deployed. Monthly is 50% cheaper than hourly, and yearly is 65% cheaper. See [On demand vs. Reserved](/docs/billing/on-demand-vs-reserved) for how each method is billed. Billing methods can only be upgraded: hourly to monthly, hourly to yearly, or monthly to yearly. You can't move a resource back to a shorter billing method. ## Before you upgrade These resources can't be upgraded: * Resources already in a Reserved project, including yearly servers. **Upgrade billing method** isn't listed for them. * Servers on a legacy plan. The upgrade sidesheet shows a **Contact support** option instead. For servers, also check that: * **The server isn't locked.** **Upgrade billing method** is disabled in **Settings** while the server is locked. Unlock the server first. * **No additional IPs or VLANs are assigned** when upgrading to yearly. Remove them first. The error lists the ones still assigned. * **Your payment method can be authorized.** Upgrading to monthly or yearly needs a successful authorization on your payment method. For virtual machines, a plan resize can't be combined with a billing change. ## Upgrading a server 1. Go to the page of the server and open the **Settings** tab. 2. Select **Upgrade billing method**. 3. Choose the new billing method. 4. Type the server hostname to confirm, then select **Upgrade to monthly** or **Upgrade to yearly**. ## Upgrading a virtual machine 1. Go to the page of the virtual machine. 2. Next to **Price**, select **Save up to 65%**. 3. Choose the new billing method. 4. Type the virtual machine name to confirm, then select **Upgrade to monthly** or **Upgrade to yearly**. You can also change the billing method with the `billing` attribute of the [update server](/docs/api-reference/update-server) and [update virtual machine](/docs/api-reference/update-virtual-machine) endpoints. ## Hourly to monthly The resource stays in its current project, and billing switches to the monthly price. ## Upgrading to yearly Yearly is a Reserved billing method, so the resource moves to your team's Reserved project. If you don't have one yet, it's created for you. Yearly is paid upfront for the committed period. You get a credit for the unused time in the previous project. Elastic IPs assigned to a server are unassigned when it moves to the Reserved project. ## SSH keys and User Data Changing the billing method takes no action on the machine itself. Nothing is reinstalled, and the SSH keys already on the operating system stay in place. When a server moves to the Reserved project, its saved deploy settings are reset. On the next reinstall, select your SSH keys and User Data again. * **Team** [SSH keys](/docs/servers/ssh-keys#project-and-team-scope) and [User Data](/docs/servers/user-data#project-and-team-scope) are available in every project, including the Reserved one. * **Project** SSH keys and User Data stay with their original project and aren't listed in the Reserved project. # Invoices Source: https://www.latitude.sh/docs/billing/invoices ![Invoices overview](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/48.Docs25Q4.InvoicesOverview.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=2594d297e7b2b624ee62c944625f108e) ## Remaining and Unused time Your invoices might contain line items that look like this ![An invoice with Remaining and Unused time line-items.](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/51.Docs25Q4.UnusedTime.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=8bf646dcc87c830285b248094a08cf89) The *Remaining* and *Unused time* line-items are Prorations. They indicate that a service was either added or removed from your Project during the billing cycle. * When you remove a service from your Project, the *Unused time* item adds a credit to your next invoice. * When you add a server to your Project, the *Remaining time* item adds a debit to your invoice referring to the date you added the service up until the service renewal. * If you add and remove the same service during the same billing cycle, you will only be charged for the time you actually used it. ## Invoices * Each [Project](/docs/projects) is a different subscription. You will receive a separate invoice for each of your Projects. * Payment methods are managed per Team. If you want to use a different payment method for each Project, reach out to support. ### Detailed invoices To view details of an invoice, go to the [dashboard](https://www.latitude.sh/dashboard/), navigate to **Usage & billing** > **Invoices**, and click **View**. Here is an example of what a detailed invoice might look like. ![Resources associated with a line item on a detailed invoice](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/49.Docs25Q4.DetailedInvoices.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=5bc154dfda096c9af0354cbca095bfa8) #### Line item discounts When discounts are applied to specific line items, they are displayed both in the dashboard and PDF exports: * **Dashboard view**: Discounts appear in a dedicated "Discount" column showing the discount amount with a tooltip containing the discount name and percentage (if applicable) * **PDF export**: Discount information is shown below each applicable line item, including the discount name and percentage off when available Line item discounts provide granular visibility into how discounts are applied to individual services, separate from any total invoice discounts that may appear in the invoice summary. The invoice can be exported in PDF and CSV. Unlike the invoice received by email, these files make it much easier to track cloud resources at their cost. To generate the files, choose the format in the upper right corner. ![Invoice download options](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/50.Docs25Q4.DownloadInvoice.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=c50f934d143fc86c2d80c36db98b1e15) Detailed invoices are useful when you want to see which cloud resources are associated with your bill. It has more information than the PDF invoice that is sent to your email as it shows a description for each line, and, in the case of servers, allows you to expand the line item and see which server is associated with it. Each line item also retrieves a unique identifier that you can use to track costs on your own systems. # On demand vs. Reserved Source: https://www.latitude.sh/docs/billing/on-demand-vs-reserved ## On demand ### Hourly *A good option for projects that are not sure about the long-term commitment or just want to test the platform.* Create and delete servers as you wish with no long-term commitments, paying only for the time you use. The price is calculated based on an average of 730 hours each month. As not all months have the same number of hours, the price of hourly servers will fluctuate slightly for each billing cycle. All you need to deploy an On demand server is to make sure the project billing type is set to *On demand* when creating a project. You can view this information on the *Home* page of your dashboard. ### Monthly *A good option for projects that want to have more predictability over their costs and workloads and want to save compared to the hourly price.* * **50% discount** over the hourly price for [Metal](https://www.latitude.sh/features) and for [Accelerate](https://www.latitude.sh/accelerate). * More predictability over your costs as price stays consistent over the months. * Deleting a server does not create pro-rations, and refunds are not offered. When deleting an On demand monthly server, make sure you only delete it when it's close to the renewal period. ## Reserved *Provides the most significant savings. Great for predictable workloads and cost management.* * **65% cheaper** than the hourly price. * Considerably reduce costs by committing to a server configuration. * By reserving an instance, you commit to the configuration, not the instance itself, so you can still upgrade or change instances during the contract. Reserved instances are always paid upfront for the committed period. ## Upgrading an existing resource You can move a deployed server or virtual machine to monthly or yearly billing. See [Changing the billing method](/docs/billing/change-billing-method). # Billing Source: https://www.latitude.sh/docs/billing/overview Understanding and managing billing for your Latitude.sh projects is made as simple as possible. You can manage everything related to how and when your projects are billed by going to **Settings & Billing** on the dashboard. ![Billing and invoices section on the Latitude.sh dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/47.Docs25Q4.BillingOverview.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=f3caa7b2372f6e8aec9bda81e9322f08) If you have issues or questions not covered by this documentation, feel free to reach out to the team by [creating a support ticket](https://www.latitude.sh/dashboard/support). # Payment methods Source: https://www.latitude.sh/docs/billing/payment-methods Each Project you create is a different subscription, and you receive a separate invoice for each project. Payment methods, on the other hand, are used for the whole [Team](/docs/teams). ## Accepted payment methods | Payment method | Countries supported | | :- | :- | | Credit card | All | | Wire transfers (on request) | All | | Boleto Bancário | Brazil | | PIX | Brazil | | Apple Pay | [All supported countries](https://support.apple.com/en-us/HT207957) | | Google Pay | [All supported countries](https://support.google.com/pay/answer/9023773?hl=en\&ref_topic=7625138) | | ACH | United States | | Alipay | China | | WeChat Pay | China | | Bancontact | Belgium | | EPS | Austria | | Giropay | Germany | | iDEAL | Netherlands | | Przelewy24 | Poland | | Sofort | Germany, Austria, Switzerland | ## Adding a card Log in to the dashboard and click on **Usage & Billing**. On the billing page, click on **Add new**. When adding a card, a **hold of \$5** is automatically placed on your card. The amount is automatically refunded after 7 days. ## Adding Credits with Crypto or Card ### Credits Credits are automatically applied to future invoices. When an invoice is paid in full or in part with credits, it will be displayed on your invoice as a discount applied. > [!NOTE] > > Credits can only be purchased if the team's currency is USD. To purchase credits, navigate to **Usage & Billing > Billing**, locate the **Credits** section, and click on **Add credits**. **Using Credit Card** 1. In the Credit Card tab, enter the amount you wish to add and click **Continue**. 2. Ensure you have a default credit card set up. **Using Crypto** 1. In the Crypto tab, enter the amount you wish to add. 2. Choose between the Solana or Ethereum blockchain and click **Continue**. 3. Ensure you have a wallet compatible with the selected blockchain. 4. Payments will be processed in USDC tokens. After payment, credits will be added immediately to your account. They can be verified in **Usage & Billing > Billing** under the **Credits** section. # Resource Limits Source: https://www.latitude.sh/docs/billing/resource-limits View your team's current usage and quotas across all resources. If you need more capacity, you can request a quota increase. To view resource limits, go to **Usage & billing** > **Resource quotas**. ## Understanding resource limits Your team has limits on the following resources: * **Bare Metal**: Total number of bare metal servers * **Bare Metal GPU**: Total number of GPU bare metal servers * **Virtual Machines**: Total number of virtual machines in use across all projects * **Databases**: Total number of managed databases * **Filesystem**: Total number of filesystems * **Block Storage**: Total number of block storage volumes * **VLANs**: Total number of private networks (VLANs) in use across all projects Each resource shows: * **Current usage**: Resources or capacity currently in use across all projects * **Limit**: Maximum allowed quota (shown as ∞ for unlimited resources) * **Usage gauge**: Visual indicator of usage as a percentage of your limit ## Requesting a quota increase **1. Navigate to Resource quotas** Go to **Usage & billing** > **Resource quotas**. **2. Request increase** Click **Request increase** next to the resource you need more capacity for. Resources marked "Not adjustable" can't be increased. **3. Fill in request details** The modal shows your current usage and limit with a visual gauge. * **New limit**: Enter the new quota. Pre-filled with a suggested value (one more than your current limit, or one more than your usage if over the limit). * **Business justification**: Explain why you need the increase. Click **Submit request**. **4. Approval** Your request is sent to the Latitude team for review. You'll be notified when it's approved or denied. Once approved, your quota updates automatically. ## Permissions # Latitude.sh CLI Source: https://www.latitude.sh/docs/cli `lsh` is Latitude.sh's command line interface. [Free and open source](https://github.com/latitudesh/cli). `lsh` is the easiest way to deploy and manage your infrastructure without leaving the terminal. Use `lsh` to work with servers, settings and more. > [!NOTE] > > The CLI is open source and contributions are welcome. Go to the Github repo, > share what you'd like to see, or open a PR with your suggestions! ### Try Latitude.sh on the command line Install on MacOS, Linux or WSL: Using Homebrew ```shell theme={null} brew install latitudesh/tools/lsh ``` Using the installation script ```shell theme={null} curl -fsSL https://cli.latitude.sh/install.sh | sh ``` After installation concludes, the `lsh` command should be available. ### Getting started Using `lsh` is as easy as using the API or dashboard. The response is returned in a table format, but JSON is also available by passing the `--json` argument. ### Authentication The CLI supports two authentication methods: **Browser-assisted login (recommended)** Run `lsh login` without arguments. The CLI opens your browser to authorize the session: ```shell theme={null} lsh login ``` 1. A verification code appears in your terminal 2. Your browser opens to the authorization page 3. Confirm the code matches, select a team, and click **Authorize** 4. Return to your terminal—you're logged in **API key login** You can authenticate directly with an API key. Create one from **Settings → API Keys** in the [dashboard](https://www.latitude.sh/dashboard), then run: ```shell theme={null} lsh login --with-token ``` **Profiles** The CLI stores one profile per team you log into. Run `lsh login` again to add another team, switch between them with `lsh profile use`, and check the active profile with `lsh auth status`. See [Commands](/docs/cli/commands#profiles) for details. # Commands Source: https://www.latitude.sh/docs/cli/commands ## General **Log in to Latitude.sh** ```shell theme={null} lsh login ``` Opens your browser for browser-assisted authentication. To authenticate with an API key instead, pass it as an argument: ```shell theme={null} lsh login --with-token ``` **Update the CLI to latest version** ```shell theme={null} lsh update ``` **Generate a shell completion script** ```shell theme={null} lsh completion ``` ## Api Keys **Create an API Key** ```shell theme={null} lsh api_keys create ``` **Delete an API Key** ```shell theme={null} lsh api_keys destroy ``` **List API Keys** ```shell theme={null} lsh api_keys list ``` **Update an API Key** ```shell theme={null} lsh api_keys update ``` ## Auth **Show the current authentication context** ```shell theme={null} lsh auth status ``` Shows the active profile's email, team and API key, plus every other stored profile. Pass `--check` to validate each stored token against the API. **Log out** ```shell theme={null} lsh auth logout ``` Removes the stored profile and, for browser logins, revokes the API key. Pass `--profile ` to log out a specific profile, or `--all` to log out every stored profile. ## Elastic IPs **List Elastic IPs** ```shell theme={null} lsh elastic-ips list ``` Lists all Elastic IPs in the team. `ls` is available as an alias. Filter with `--project`, `--server`, and `--status`, where status is one of `configuring`, `active`, `moving`, `releasing`, or `error`. **Retrieve an Elastic IP** ```shell theme={null} lsh elastic-ips get ``` **Create an Elastic IP** ```shell theme={null} lsh elastic-ips create --project --server ``` Both `--project` and `--server` are required: the API allocates the IP in the target server's region and assigns it there. Allocation is asynchronous, so the new IP starts in the `configuring` status until provisioning completes. **Move an Elastic IP to another server** ```shell theme={null} lsh elastic-ips update --server ``` Reassigns the Elastic IP to another server in the same project. **Delete an Elastic IP** ```shell theme={null} lsh elastic-ips delete ``` Releases the Elastic IP. `rm` is available as an alias. ## Events **List team audit events** ```shell theme={null} lsh events list ``` Lists the team's audit events, newest first, with automatic pagination. Filter the results with `--author` (ID or email), `--project` (ID or slug), `--target-type` (repeatable, e.g. `servers`, `projects`, `virtual_networks`), `--target-id`, and `--action` (e.g. `servers.create`). Use `--since` and `--until` to scope the time range. Both accept either a relative duration looking back from now (`24h`, `7d`, `2w`) or an ISO date (`2026-06-01`): ```shell theme={null} lsh events list --since 24h --target-type servers lsh events list --author user@example.com --action servers.create lsh events list --project my-project --since 2026-06-01 ``` Pass `--follow` (or `-f`) to stream new events in real time instead of printing a one-time list. The command keeps polling and prints each new event as it happens until you stop it with Ctrl+C. Combine it with the usual filters to watch a single resource: ```shell theme={null} lsh events list --follow --target-id sv_xxxx ``` `--follow` streams plain text only: `-o json`, `-o yaml`, and `-o csv` are ignored with a warning, and `--until` is ignored because the stream has no end. Following starts from the current moment unless you pass `--since` to replay recent history before streaming. ## Firewalls **List firewalls** ```shell theme={null} lsh firewalls list ``` Lists all firewalls in the team. `ls` is available as an alias. Filter by project with `--project `. In the interactive table, press Enter on a row to expand that firewall's rules. **Retrieve a firewall** ```shell theme={null} lsh firewalls get ``` **Create a firewall** ```shell theme={null} lsh firewalls create --name --project ``` `--name` and `--project` are both required. Add rules with `--rules`, passing either an inline JSON array or a file with `@path/to/rules.json`: ```shell theme={null} echo '[{"from":"ANY","to":"ANY","protocol":"TCP","port":"22","description":"SSH"}]' > rules.json lsh firewalls create --name web --project my-project --rules @rules.json ``` Each rule accepts `from`, `to`, `protocol` (`TCP` or `UDP`), `port` (a single port or a range), and an optional `description`. **Update a firewall** ```shell theme={null} lsh firewalls update --name ``` Pass `--name`, `--rules`, or both — at least one is required. Passing `--rules` replaces the firewall's entire rule set; pass `[]` to clear all rules. **Delete a firewall** ```shell theme={null} lsh firewalls delete ``` `rm` is available as an alias. ### Firewall assignments An assignment attaches a firewall to a server so the firewall's rules apply to that server's traffic. **Assign a server to a firewall** ```shell theme={null} lsh firewalls assignments create --firewall --server ``` **List firewall assignments** ```shell theme={null} lsh firewalls assignments list --firewall ``` With `--firewall`, lists the assignments of a single firewall. Omit it to list every firewall assignment in the team, optionally filtered by `--server `. **Remove a firewall assignment** ```shell theme={null} lsh firewalls assignments delete --firewall ``` `rm` is available as an alias. ## IPs **List IP addresses of a project** ```shell theme={null} lsh ips list --project ``` Pass `--all-projects` to list IPs across every project you have access to. Filter with `--server`, `--family`, `--type` and `--location`. **Retrieve an IP address** ```shell theme={null} lsh ips get ``` ## Kubernetes Manage Kubernetes clusters, list available versions, and fetch a cluster's kubeconfig. `k8s` is available as an alias: `lsh k8s clusters list`. **List clusters** ```shell theme={null} lsh kubernetes clusters list --project ``` Lists the Kubernetes clusters in a project. This endpoint accepts the project ID (`proj_xxx`) only — it does not resolve slugs. `ls` is available as an alias. **Retrieve a cluster** ```shell theme={null} lsh kubernetes clusters get ``` **Create a cluster** ```shell theme={null} lsh kubernetes clusters create --project --region --plan ``` `--project`, `--region` (site code, e.g. `SAO2`), and `--plan` (the control-plane node plan) are required. Optional flags: `--worker-plan` (defaults to the control-plane plan), `--worker-count` (defaults to 1), `--control-plane-count` (defaults to 1), `--kubernetes-version` (defaults to the latest supported), `--ssh-keys` (SSH key IDs, repeatable), `--os`, and `--name` (auto-generated if omitted). By default the command returns as soon as the request is accepted. Pass `--wait` to block until the cluster is provisioned instead. The wait fails fast if the cluster enters a failed phase, and `--timeout` (default `10m`) caps how long it waits. ```shell theme={null} lsh kubernetes clusters create --project --region SAO2 --plan c2-small-x86 --worker-count 3 --wait ``` **Delete a cluster** ```shell theme={null} lsh kubernetes clusters delete ``` `rm` is available as an alias: `lsh kubernetes clusters rm `. **List available Kubernetes versions** ```shell theme={null} lsh kubernetes versions list ``` **Fetch a cluster's kubeconfig** ```shell theme={null} lsh kubernetes kubeconfig ``` Prints the cluster's kubeconfig as raw YAML to stdout. Redirect it to a file to use with kubectl: ```shell theme={null} lsh kubernetes kubeconfig > kubeconfig.yaml ``` ## Operating Systems **List operating systems available for deployment** ```shell theme={null} lsh operating-systems list ``` `os` is available as an alias: `lsh os list`. ## Plans **Retrieve information of a plan** ```shell theme={null} lsh plans get ``` **List available plans** ```shell theme={null} lsh plans list ``` **List bandwidth package plans** ```shell theme={null} lsh plans list-bandwidth ``` **Show per-location plan availability and stock level** ```shell theme={null} lsh plans stock ``` ## Profiles The CLI stores one profile per team you are logged into. The active profile defines the team your commands run against. **List stored profiles** ```shell theme={null} lsh profile list ``` **Switch the active profile** ```shell theme={null} lsh profile use ``` You can also set the profile for a single command with the global `--profile` flag or the `LSH_PROFILE` environment variable. ## Projects **Create a project** ```shell theme={null} lsh projects create ``` **Delete a project** ```shell theme={null} lsh projects destroy ``` **Retrieve a project** ```shell theme={null} lsh projects get ``` **List projects** ```shell theme={null} lsh projects list ``` **Update a project** ```shell theme={null} lsh projects update ``` ## Regions **List available regions** ```shell theme={null} lsh regions list ``` ## Servers **Deploy a bare metal server** ```shell theme={null} lsh servers create ``` **Delete a server** ```shell theme={null} lsh servers destroy ``` **Get information on a server** ```shell theme={null} lsh servers get ``` **List servers** ```shell theme={null} lsh servers list ``` **Reinstall a server** ```shell theme={null} lsh servers reinstall ``` **Wait for a server to finish provisioning** By default, `servers create` and `servers reinstall` return as soon as the request is accepted. Pass `--wait` to block until the server settles into a stable state (`on` or `off`) instead, which is useful in scripts and CI pipelines where the next step depends on the server being ready. ```shell theme={null} lsh servers create --project --site --plan --operating_system --hostname --wait ``` The wait fails fast if the server enters a failed deployment state, and `--timeout` (default `10m`) caps how long it waits — on timeout the command exits with a non-zero status. Progress is written to stderr while the final server state goes to stdout, so `-o json`, `-o yaml`, and `-o csv` are still honored. ```shell theme={null} lsh servers create ... --wait --timeout 30s ``` **Power on, off, or reboot a server** ```shell theme={null} lsh servers power-on lsh servers power-off lsh servers reboot ``` Each power action is its own subcommand. Pass `--wait` to block until the server reaches the target power state — `on` for `power-on` and `reboot`, `off` for `power-off` — instead of returning as soon as the request is accepted. `power-on` and `power-off` return immediately when the server is already in the target state, while `reboot` waits to observe the power cycle. As with provisioning, `--timeout` (default `10m`) caps the wait, progress is written to stderr, and the wait fails fast if the server enters a failed deployment state. ```shell theme={null} lsh servers reboot --wait ``` **Boot a server into rescue mode** ```shell theme={null} lsh servers rescue-mode lsh servers exit-rescue-mode ``` `rescue-mode` reboots the server into a lightweight recovery environment, and `exit-rescue-mode` reboots it back into its installed operating system. Both accept `--wait`: `rescue-mode` waits for the server to reach the `rescue_mode` state, and `exit-rescue-mode` waits for it to settle back to `on` or `off`. The API doesn't return the rescue login credentials — find them on the server's page in the dashboard. See [Rescue mode](/docs/servers/rescue-mode) for the full recovery workflow. **Lock or unlock a server** ```shell theme={null} lsh servers lock lsh servers unlock ``` Locking a server prevents destructive actions such as deletion, reinstall, and power changes. Unlock it to allow those actions again. **Schedule deletion** ```shell theme={null} lsh servers schedule-deletion ``` **Unschedule deletion** ```shell theme={null} lsh servers unschedule-deletion ``` **Update a server** ```shell theme={null} lsh servers update ``` ## SSH Keys The `lsh ssh-keys` commands manage your team's SSH keys at the account level. To manage the keys inside a specific project, use [`lsh projects ssh-keys`](#project-ssh-keys) instead. The legacy `ssh_keys` name still works as a hidden alias. **List SSH keys** ```shell theme={null} lsh ssh-keys list ``` Filter by tag with `--tags `. Lists paginate automatically; use `--page-size`, `--max-items`, or `--no-paginate` to control paging. `ls` is available as an alias. **Retrieve an SSH key** ```shell theme={null} lsh ssh-keys get ``` **Create an SSH key** ```shell theme={null} lsh ssh-keys create --name --public-key "ssh-ed25519 AAAA..." ``` Both `--name` and `--public-key` are required. **Update an SSH key** ```shell theme={null} lsh ssh-keys update --name ``` Only the flags you pass are changed. Pass `--name` to rename the key and `--tags ` (repeatable) to associate tags. **Delete an SSH key** ```shell theme={null} lsh ssh-keys delete ``` `rm` is available as an alias. **Manage a project's SSH keys** ```shell theme={null} lsh projects ssh-keys list --project lsh projects ssh-keys get --project lsh projects ssh-keys create --project --name --public-key "ssh-ed25519 AAAA..." lsh projects ssh-keys delete --project ``` The `projects ssh-keys` commands (`list`, `get`, `create`, and `delete`) manage SSH keys scoped to a project. `create` adds a new key to the project and `delete` removes it entirely, rather than detaching a team key. Commands default to the active project, so `--project` is optional once one is set. ## Storage Filesystems Manage file storage volumes in a project. Filesystems are created from the dashboard; the CLI lists, resizes, and deletes them. **List filesystems** ```shell theme={null} lsh storage-filesystems list --project ``` `ls` is available as an alias. Pass `--project` to filter to a single project. **Resize a filesystem** ```shell theme={null} lsh storage-filesystems update --size ``` Size is the only field you can update. `--size` is required and must be a positive number of GB; otherwise the command fails before making any request. **Delete a filesystem** ```shell theme={null} lsh storage-filesystems delete ``` `rm` is available as an alias. ## Storage Objects Manage S3-compatible object storage buckets in a project. **List buckets** ```shell theme={null} lsh storage-objects list --project ``` `ls` is available as an alias. Pass `--project` to filter to a single project. **Retrieve a bucket** ```shell theme={null} lsh storage-objects get ``` **Create a bucket** ```shell theme={null} lsh storage-objects create --project --name --region ``` `--project`, `--name`, and `--region` are required. `--region` takes a site slug (for example, `DAL`). Optionally pass `--storage-class` (`standard` or `high_performance`), `--versioning` to enable object versioning, and `--locking` to enable object lock (WORM). Object lock requires versioning, so `--locking` enables it automatically. ```shell theme={null} lsh storage-objects create --project my-project --name logs --region DAL --storage-class high_performance --versioning ``` **Delete a bucket** ```shell theme={null} lsh storage-objects delete ``` The bucket must be empty. `rm` is available as an alias. ## Tags **Create a Tag** ```shell theme={null} lsh tags create ``` **Delete Tag** ```shell theme={null} lsh tags destroy ``` **List all Tags** ```shell theme={null} lsh tags list ``` **Update Tag** ```shell theme={null} lsh tags update ``` The `lsh tags` commands manage the tags themselves. To attach a tag to a resource, pass `--tags` to that resource's own update command: ```shell theme={null} lsh servers update --id --tags lsh projects update --id --tags ``` ## Traffic **Show traffic consumption** ```shell theme={null} lsh traffic list --project ``` Shows bandwidth consumption per region for a project, mirroring the dashboard: inbound and outbound totals, the quota, and how much of it has been used. Units follow the project's billing method — TB for volume billing, Mbps for 95th-percentile billing. A project is required; in an interactive terminal you're prompted to pick one when `--project` is omitted. The range defaults to the last 7 days. Override it with `--since` and `--until`, which accept a duration (`24h`, `7d`, `2w`) or an ISO date (`2026-06-01`). The range applies to consumption only — the quota column always reflects the current limit. Pass `--daily` for the day-by-day breakdown behind the dashboard chart. ```shell theme={null} lsh traffic list --project my-project --daily lsh traffic list --project my-project --since 30d lsh traffic list --project my-project --since 2026-05-01 --until 2026-06-01 ``` **Show traffic quota** ```shell theme={null} lsh traffic quota ``` Shows the traffic quota of each project, per region. Pass `--project` to filter to a single project. ## Teams > [!NOTE] > > Team and member operations are interactive: when you omit an argument or > required flag, the CLI prompts you for it in the terminal. **List your teams** ```shell theme={null} lsh teams list ``` **Create a team** ```shell theme={null} lsh teams create --name --currency ``` **Update a team** ```shell theme={null} lsh teams update --name ``` **List members of the current team** ```shell theme={null} lsh teams members list ``` **Invite a user to the current team** ```shell theme={null} lsh teams members add --email --role ``` Roles: `owner`, `administrator`, `collaborator` or `billing`. **Remove a user from the current team** ```shell theme={null} lsh teams members remove ``` ## User Data The `lsh user-data` commands manage your team's [user data](/docs/servers/user-data) scripts at the account level. To manage the user data inside a specific project, use [`lsh projects user-data`](#project-user-data) instead. The API stores user data content base64-encoded. To keep things simple, `--content` takes plain text and encodes it for you, while `--content-base64` passes an already-encoded value through unchanged. The two flags are mutually exclusive. **List user data** ```shell theme={null} lsh user-data list ``` `ls` is available as an alias. Lists show a compact table without the base64 content, and paginate automatically; use `--page-size`, `--max-items`, or `--no-paginate` to control paging. **Retrieve a user data entry** ```shell theme={null} lsh user-data get ``` The details view decodes and shows the cloud-init content, and is scrollable for longer scripts. **Create a user data entry** ```shell theme={null} lsh user-data create --description --content "#cloud-config" ``` `--description` is required. Pass the script with either `--content` (plain text) or `--content-base64` (already encoded). **Update a user data entry** ```shell theme={null} lsh user-data update --description ``` Only the flags you pass are changed. Provide at least one of `--description` or `--content`/`--content-base64`. **Delete a user data entry** ```shell theme={null} lsh user-data delete ``` `rm` is available as an alias. **Manage a project's user data** ```shell theme={null} lsh projects user-data list --project lsh projects user-data get --project lsh projects user-data create --project --description --content "#cloud-config" lsh projects user-data update --project --description lsh projects user-data delete --project ``` The `projects user-data` commands manage user data scoped to a project, with the same `--content` and `--content-base64` handling as the account-level commands. Commands default to the active project, so `--project` is optional once one is set. Unlike the other list commands, `projects user-data list` returns a single page; the pagination flags are accepted but have no effect. ## Virtual Machines `vm` and `vms` are available as aliases: `lsh vm list`, `lsh vms get `. **List virtual machines** ```shell theme={null} lsh virtual-machines list ``` Lists every virtual machine in the team. Filter with `--project ` and `--tags ` (repeatable or comma-separated). **Retrieve a virtual machine** ```shell theme={null} lsh virtual-machines get ``` **Create a virtual machine** ```shell theme={null} lsh virtual-machines create --plan --project ``` `--plan` and `--project` are required. Pass the plan ID (`plan_xxx`) — virtual machine plans have no slug. Optional flags: `--name` (hostname), `--region` (site slug, e.g. `DAL`; defaults to `DAL`), `--os` (operating system slug), `--ssh-keys` (SSH key IDs, repeatable), `--user-data` (a user data record reference such as `ud_xxx`, applied as cloud-init), and `--tags` (tag IDs, repeatable). By default the command returns as soon as the request is accepted. Pass `--wait` to block until the VM reaches the `Running` state instead. `--timeout` (default `10m`) caps the wait; on timeout the command exits with a non-zero status. Progress is written to stderr and the final state to stdout, so `-o json`, `-o yaml`, and `-o csv` are honored. ```shell theme={null} lsh virtual-machines create --plan --project --region DAL --name my-vm --wait ``` **Update a virtual machine** ```shell theme={null} lsh virtual-machines update --name ``` Updates the virtual machine's name or tags. Pass `--name` and/or `--tags` (tag IDs; replaces all existing tags) — at least one is required. **Run a power action** ```shell theme={null} lsh virtual-machines action --action ``` `--action` is required and must be one of `power_on`, `power_off`, or `reboot`. **Delete a virtual machine** ```shell theme={null} lsh virtual-machines delete ``` `rm` is available as an alias: `lsh virtual-machines rm `. ## Virtual Networks **Creates a virtual network** ```shell theme={null} lsh virtual_networks create ``` **Delete a virtual network** ```shell theme={null} lsh virtual_networks destroy ``` **Retrieve a virtual network** ```shell theme={null} lsh virtual_networks get ``` **List virtual networks** ```shell theme={null} lsh virtual_networks list ``` **Update a virtual network** ```shell theme={null} lsh virtual_networks update ``` ## Virtual Networks Assignments **Assign a server to a virtual network** ```shell theme={null} lsh assignments virtual_networks create ``` **Unassign a server from a virtual network** ```shell theme={null} lsh assignments virtual_networks destroy ``` **List assignments** ```shell theme={null} lsh assignments virtual_networks list ``` ## Help * Use `lsh -h` to get a list of all available commands * To see how to use a command, use `lsh -h` The CLI also ships built-in help topics with longer guides: ```shell theme={null} lsh authentication # How to sign in: tokens, profiles, env vars lsh profiles # How profiles map to teams lsh automation # Run lsh non-interactively (CI, scripts, AI agents) lsh output-formats # Render results as table, JSON, YAML or CSV (with JMESPath queries) ``` See [Output formats & automation](/docs/cli/output-formats) for the full guide to machine-readable output, `--query` filtering, and pagination. # Examples Source: https://www.latitude.sh/docs/cli/examples ### Create a server ```shell theme={null} lsh servers create --operating_system ubuntu_22_04_x64_lts --project --site --hostname --plan ``` ### Assign the created server to a virtual network ```shell theme={null} # Create a virtual network in the same location lsh virtual_networks create --description --project --site # Find the virtual network if you don't have the id lsh virtual_networks list --location # Find the server if you don't have the id lsh servers list --hostname # Assign the server with the server_id and virtual_network_id created lsh virtual_networks assignments create --virtual_network_id --server_id ``` ### List all GPU plans ```shell theme={null} lsh plans list --gpu true ``` ### Check plan availability per location `lsh plans stock` flattens the `/plans` API response into one row per plan × location, so you can see exactly where each plan has stock right now. ```shell theme={null} lsh plans stock ``` Show only locations that currently have stock: ```shell theme={null} lsh plans stock --in_stock ``` Filter by region and export as CSV: ```shell theme={null} lsh plans stock --region "United States" --in_stock -o csv > us_plans.csv ``` Combine filters and pipe to `jq` (use `-o json` when piping — the default table is meant for humans): ```shell theme={null} lsh plans stock --gpu --ram_gte 64 -o json | jq '.[] | {plan: .plan_slug, loc: .location, stock: .stock_level}' ``` **Available filters:** `--region`, `--location` (alias `--site`), `--name`, `--slug`, `--gpu`, `--in_stock` (alias `--available`), `--stock_level` (`Unavailable`, `Low`, `Medium`, `High`, `Unique`), `--ram_eql` / `--ram_gte` / `--ram_lte`, `--disk_eql` / `--disk_gte` / `--disk_lte`. **Output formats:** `-o table|json|yaml|csv` (see [Output formats & automation](/docs/cli/output-formats)). **How `stock_level` is derived per location** The `/plans` API reports `stock_level` at the **region** level, plus two location lists: * `locations.available` — where the plan can be deployed at all * `locations.in_stock` — where there is inventory right now Each row emitted by `plans stock` gets its `stock_level` resolved per location: * if the location is in `in_stock` → it inherits the region's `stock_level` * otherwise → `unavailable` For example, if `c3-large-x86` reports `stock_level: high` in **United States** with `available: [DAL, LAX, NYC, CHI, ASH, MIA2, LAX2, SJC2, ASH2]` and `in_stock: [LAX, NYC, CHI, MIA2]`, the CLI outputs `high` for LAX/NYC/CHI/MIA2 and `unavailable` for the other five — so you never assume a location has stock just because the region does. ### Create an on-demand project ```shell theme={null} lsh projects create --description --name --provisioning_type on_demand ``` ### Setting the output as a JSON It is possible to render JSON if you want to see different fields or even parse the data using a JSON processor like [jq](https://jqlang.github.io/jq/). To format the output to JSON, you must pass `-o json` or `—-json`. **Example** ```shell theme={null} lsh servers list -o json # or lsh servers list --json ``` # Output formats & automation Source: https://www.latitude.sh/docs/cli/output-formats Render lsh list results as JSON, YAML, or CSV, filter them with JMESPath, and control pagination for scripts, CI, and AI agents Every `lsh` `list` command can render its results in a machine-readable format that's easy to consume from scripts, CI pipelines, and AI agents. Output format, filtering, and pagination all work the same way across every list command. You can also run `lsh output-formats` for the built-in version of this guide. ## Output formats Use the global `--output` (or `-o`) flag to choose how results are rendered. The default is a human-readable table. ```shell theme={null} lsh servers list -o table # human-readable table (default) lsh servers list -o json # JSON lsh servers list -o yaml # YAML lsh servers list -o csv # CSV (header row + one row per item) lsh servers list --json # shortcut for -o json ``` Structured formats (`json`, `yaml`, `csv`) are honored everywhere, including when you pipe the output to another command. An empty result set prints `[]` in JSON, so your scripts always receive valid JSON to parse. ## Filtering with `--query` The `--query` flag post-processes structured output with a [JMESPath](https://jmespath.org/) expression, so you can filter and reshape results without piping to `jq` or another tool. It works with `json`, `yaml`, and `csv`. ```shell theme={null} # Only the IDs of servers that are powered on lsh servers list --query "[?status=='on'].id" -o json # A projection of selected fields lsh servers list --query "[].{id: id, host: hostname}" -o yaml ``` `--query` requires a structured output format, so pair it with `-o json`, `-o yaml`, or `-o csv`. The expression is validated up front: an invalid query fails immediately with a non-zero exit code instead of producing partial output. ## Pagination List commands fetch every page by default. These global flags give you control over large listings: | Flag | Purpose | | - | - | | `--page-size ` | Items requested per API page (default `100`). | | `--max-items ` | Stop after `N` items across all pages (`0` = no limit). | | `--no-paginate` | Fetch only the first page. If more results exist, the next page number is printed to `stderr` so you can resume. | ```shell theme={null} lsh servers list --page-size 10 --max-items 50 # at most 50 items, fetched in pages of 10 lsh servers list --no-paginate -o json # first page only ``` ## Environment variables | Variable | Purpose | | - | - | | `LSH_OUTPUT` | Default output format (`table`, `json`, `yaml`, or `csv`). Precedence is `--output` flag > `LSH_OUTPUT` > config file > default (`table`). | | `LSH_CLASSIC_OUTPUT` | Set to `true` to force the legacy plain-ASCII table. An explicit `-o json/yaml/csv` still takes precedence. | Set `LSH_OUTPUT` to avoid passing `-o` on every command: ```shell theme={null} export LSH_OUTPUT=json lsh servers list # prints JSON ``` # SDKs Source: https://www.latitude.sh/docs/client-libraries Official SDKs for the Latitude.sh API We currently have three official SDKs that make it easy to work with the Latitude.sh API. > **[TypeScript SDK](https://github.com/latitudesh/latitudesh-typescript-sdk)** > **[Go SDK](https://github.com/latitudesh/latitudesh-go-sdk)** > **[Python SDK](https://github.com/latitudesh/latitudesh-python-sdk)** # Command menu Source: https://www.latitude.sh/docs/dashboard/command-menu The Command Menu makes it easy to navigate the dashboard and search for resources faster than you would with a cursor. ![Command Menu](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/3.Docs25Q4.CmdK.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=62074a8ceb926b8115e61eff38b35298) Hit `⌘` + `K` on Mac or `Ctrl` + `K` on Windows to access it. To use the Command Menu, use your cursor or the keyboard's `↑` and `↓`. Hit `↵` to go to the highlighted item. If you go to a secondary section, for example when clicking on the *Help* item, use the *backspace* to go back to the previous section. The Command Menu works everywhere on the dashboard and presents items based on which page you are. ## Server search The Command Menu supports multiple ways to find servers: * **Server ID**: Enter the full server ID (e.g., `sv_abc123def456g`) to jump directly to that server * **IP address**: Enter an IPv4 or IPv6 address to find the server it's assigned to * **Hostname or label**: Enter text to find servers matching their hostname or label Server ID and IP address searches perform exact lookups, while hostname searches match partial text. The same search capabilities are available in the server list filter. ## Keyboard Shortcuts * `Ctrl/Command` + `K`: Opens the Command Menu * `Shift` + `S`: Opens the server search list * `Shift` + `T`: Opens team selection * `Shift` + `P`: Opens project selection * `Shift` + `?`: Opens the help menu * `t`: Toggles between light and dark theme # Filters and views Source: https://www.latitude.sh/docs/dashboard/filters-and-views ## Filters ![Filters and views interface](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/34.Docs25Q4.Views.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=a51d545b5ca0abb8e6416e90865bbbfe) Filters are a powerful way to gain visibility into your resources and their current state. You can combine multiple filters to your exact needs. ### Quick search The server list includes a quick search bar that supports multiple lookup methods: * **Server ID**: Enter the full server ID (e.g., `sv_abc123def456g`) to navigate directly to that server * **IP address**: Enter an IPv4 or IPv6 address to find and navigate to the server it's assigned to * **Hostname or label**: Enter text to find servers matching their hostname or label Server ID and IP address searches are exact lookups that take you directly to the matching server. Hostname and label searches match partial text. ### Filter conditions Query refinement can be done using filter conditions. When condition options are available, the symbol between the filter name and the value will be highlighted and turn interactive. Clicking on the symbol will open a dropdown menu of available conditions. Each filter has its own set of best suited conditions (e.g, for Hostname filter there are "contains", "is equal to", "starts with" and "ends with"). ### Sorting Sorting helps you organize resource lists by the criteria that matter most. To change the sorting criteria, click on the current sorting applied (e.g Created) and a dropdown menu of available sorting options will be shown. To alternate between ascending and descending order, click on the arrow icon to toggle the sorting order. ## Views Applied filters can be saved as Views, with each view getting its own URL so it can be shared with other team members or bookmarked. To create a view, set up the filtering options you want to apply and click on the `Save` button, type in a name and confirm. ![Create custom view interface](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/35.Docs25Q4.CreateView.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=90727eff2b95124bfb80a1738df1ac31) ### Creating Custom Views To create a custom view: 1. Apply the filters you want to save on any resource list page 2. Click the **+** (plus) button that appears next to the view selector when filters are active 3. Enter a name for your custom view 4. Click **Create** to save the view The new view will be available in the view selector dropdown and will be accessible to all team members on your account. ### Managing Custom Views Once you've created custom views, you can manage them using the options menu: * **Rename**: Click the three-dot menu (⋮) next to a custom view to rename it * **Delete**: Use the same menu to permanently delete custom views you no longer need Note that built-in views cannot be renamed or deleted - these management options are only available for custom views you create. ### View features * Each view gets its own unique URL for easy sharing and bookmarking * Views are shared automatically with all team members * You can create unlimited custom views * Views persist your exact filter combinations for quick access Views appear on the list page as an option under the filter menu and are always available to all team members on your account. You can create as many views as you want and edit them later as you wish. Views are currently available for Servers and IP Addresses. # Dashboard Source: https://www.latitude.sh/docs/dashboard/overview A tour of the Latitude.sh dashboard: the topbar, the sidebar, and how to move between teams and projects. The [Latitude.sh dashboard](https://www.latitude.sh/dashboard) is where you manage your teams, projects, and resources: servers, virtual machines, network, storage, and everything else you deploy. Take the guided tour below, or read on for what each area does. [Dashboard Overview](https://demo.arcade.software/sjNPzHRssWtrJYV80sLQ?embed\&embed_mobile=tab\&embed_desktop=inline\&squared=true\&disable_border=true\&show_copy_link=true\&utm_content=/docs/dashboard/overview) ## Topbar ### Team switcher The team switcher sits in the top left corner. Everything in the dashboard is scoped to the team you pick here: each team is a separate context, with its own projects, resources, billing, and members. ![Team switcher menu with the list of teams, Create new team, Theme, account, and Sign out](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.TeamSwitcher.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=69a085857dbde9dae8e39f4a01cf6c4f) Open the switcher to: * **Switch teams**: pick another team from the list to move between them. * **Create new team**: need a separate space for another company or client? [Create a new team](/docs/teams/create-team) from this menu. * **Theme**: choose system, light, or dark. It applies to the whole dashboard. * **Account**: your email and role in the current team. Click it to open your account and user preferences. * **Sign out**: ends your session on this device. ### Feedback Click **Feedback** in the top right corner to share your thoughts with us. Type your message, select an emoji that matches your experience, and hit **Send**. It lands with the product team, and we read every one. ![Feedback popover with a text box, emoji reactions, and the Send button](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Feedback.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=e3abc11acfc87b399765c919fbd2980d) Feedback is one-way. If you need a reply, [open a support ticket](/docs/support/contact-support) instead. ### Notifications The notifications icon, next to Feedback, collects important account notifications: [account verification](/docs/account-setup/verify-account), billing alerts, and overdue invoices. ![Notifications icon in the topbar](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Notifications.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=2032a789bc42e9f638f146ff061bc384) ### Add The **+** button is the fastest way to create something in the current team: ![Add menu with Create Metal, Create GPU, Add SSH Key, and Invite member](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.AddMenu.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=ee67b2b2bc2dad669b31c494c3194873) * **Create Metal**: [deploy a bare metal server](/docs/servers/deploying-a-server). Pick a plan, a location, and an OS. * **Create GPU**: deploy a bare metal server with dedicated GPUs. * **Add SSH Key**: [add an SSH key](/docs/servers/ssh-keys) once and use it across your team's resources. * **Invite member**: [invite a team member](/docs/teams/members). Roles control what they can see and do. ## Sidebar The sidebar is the primary way to navigate the dashboard. At the team scope it gives you Search, Projects, Activity, Usage & billing, and Settings. Inside a project, the middle section switches to that project's resources, such as Compute, Network, Storage, and Interconnection, plus Project settings. ### Search Search across projects, servers, and settings from one place. The search bar is the [command menu](/docs/dashboard/command-menu): the same menu you can bring up from anywhere in the dashboard with `⌘` + `K` (or `Ctrl` + `K` on Windows). ![Team switcher and search field at the top of the sidebar](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Search.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=25803cb1a026436c30d31991933f8380) ### Projects [Projects](/docs/projects) group your resources: servers, network, storage, and whatever you deploy next. Each project tracks its own usage and cost, and is billed separately. The Projects page is your home page. It lists every project in the team with its environment, resource counts for Compute, Network, and Storage, the spend and days left in the current billing cycle, and outbound traffic per region. Click a project to open it and deploy and manage its resources, or click **Create project** to start a new one. ![Projects page listing three projects with their environment, resource counts, spend, and traffic](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Projects.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=8adf50ab54f32457de4f6f4970883f1d) ### Activity [Activity](/docs/events) is the audit log for the team: who did what, and when. ![Activity page listing events with resource ID, project, author, and date](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/36.Docs25Q4.ActivityLogs.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=fac0a08da5c368770645727eef0f2e2b) ### Usage & billing Usage & billing shows spend per project, invoices, and the current billing cycle. It groups [Bandwidth](/docs/usage/bandwidth), Resources, [Invoices](/docs/billing/invoices), [Billing](/docs/billing/overview), and [Resource quotas](/docs/billing/resource-limits). ![Usage & billing submenu with Bandwidth, Resources, Invoices, Billing, and Resource quotas](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.UsageBilling.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=51b2e629a84ef506e487add41d993228) ### Settings Settings covers the team and your own account: General, [Members & access](/docs/teams/members), [Tags](/docs/tags), [API Keys](/docs/api-reference/authentication), [Referral](/docs/referral-program), and Profile. ![Settings submenu with General, Members & access, Tags, API Keys, Referral, and Profile](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Settings.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=f1aeafa92fbe7d9b71fd9cd2edb222bc) ### Support [Contact support](/docs/support/contact-support) for help or to find quick answers. The Support page has a **Team** tab, where everyone on the team can see and follow team-wide tickets, and a **Personal** tab for your own tickets. From there you can also grant [support account access](/docs/support/support-access). ![Support page on the Team tab, with Support account access and Contact support](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.Support.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=7a7dea475b57e936d09f3a886478b10f) ### Documentation and Changelog The last two items in the sidebar: **Documentation** opens these docs for in-depth guidance and troubleshooting, and **Changelog** lists the latest platform improvements. ![Documentation and Changelog links at the bottom of the sidebar](https://mintcdn.com/latitudesh/K25jU7WdDBcE43N5/images/product/Dashboard.BottomSection.png?fit=max\&auto=format\&n=K25jU7WdDBcE43N5\&q=85\&s=e938e55ac0290d69a3f181455b624654) # Waitlist Source: https://www.latitude.sh/docs/dashboard/server-waitlist The server waitlist feature enables you to queue for specific server types and locations. When the desired combination becomes available, you are notified via email. ![Join waitlist option](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/21.Docs25Q4.JoinWaitlist.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=cf4bd5c68085c1ca77fd5858905f1af0) ### How it works **1. Join the waitlist** On the server create page, select the desired server type and location. If the selected combination is unavailable, you can join the waitlist for that specific server type and location. **2. Receive notification** Once the server becomes available, you will receive an email notification. Each combination of server type and location triggers only one notification. To be alerted again, you must rejoin the waitlist after receiving the initial notification. # Developer resources Source: https://www.latitude.sh/docs/development Tools, SDKs, and resources to build and scale on Latitude.sh ## Get started > **[Generate API keys](https://www.latitude.sh/dashboard/api-keys)** ## Community & support > **[Contact support](https://www.latitude.sh/dashboard/support)** > > Get help from the support team with account and service questions > **[Product changelog](https://www.latitude.sh/changelog)** > > Stay updated with platform changes and new features > **[GitHub](https://github.com/latitudesh)** > > Explore open-source tools and contribute to the ecosystem # Cluster API Source: https://www.latitude.sh/docs/development/cluster-api # Model Context Protocol (MCP) Source: https://www.latitude.sh/docs/development/model-context-protocol Let AI agents manage your Latitude.sh infrastructure through our hosted MCP server The Latitude.sh MCP server lets AI agents and chat-based IDEs interact with the Latitude.sh API in natural language — list servers, deploy bare metal, manage networking, and more. It runs as a **hosted remote server** — for most clients there's nothing to install or run locally; you just point your MCP client at the URL below and connect. (Claude Desktop is the exception: it installs a small bundle.) > **[MCP server repository](https://github.com/latitudesh/latitudesh-mcp)** > **[Live server](https://mcp.latitude.sh)** ## How authentication works There are two ways to connect, depending on what your client supports: * **OAuth (recommended)** — Clients that support remote MCP over OAuth (Claude, Claude Code, Gemini CLI) connect to `https://mcp.latitude.sh/mcp` with **no API key in the config**. On first connect you're sent to your Latitude dashboard to approve the connection, and the server uses the key it mints for you. * **API key header** — Clients without OAuth send your Latitude.sh API key in the **`bearer`** header to the `/sse` endpoint. Grab a key from your [dashboard](https://www.latitude.sh/dashboard/api-keys). ## Server URL ```text OAuth (Streamable HTTP) theme={null} https://mcp.latitude.sh/mcp ``` ```text API key (SSE) theme={null} https://mcp.latitude.sh/sse ``` > [!NOTE] > > `/mcp` is OAuth-protected. For key-based clients use `/sse` (or > `/direct/mcp` for Streamable HTTP) and send the `bearer` header. The optional > `latitude-api-key` and `server-index` headers are also accepted. ## Connect your client **Claude Code** Connect over OAuth — no API key needed. Run: ```bash theme={null} claude mcp add --transport http Latitudesh https://mcp.latitude.sh/mcp ``` On first use, Claude Code opens your browser to approve the connection in your Latitude dashboard. **Gemini CLI** Connect over OAuth — no API key needed. Run: ```bash theme={null} gemini mcp add --transport http Latitudesh https://mcp.latitude.sh/mcp ``` Approve the connection in your Latitude dashboard when prompted. **Cursor** Open **Settings → Tools and Integrations → New MCP Server** and paste (replace `YOUR_LATITUDE_API_KEY`): ```json theme={null} { "mcpServers": { "Latitudesh": { "command": "npx", "args": [ "-y", "mcp-remote@latest", "https://mcp.latitude.sh/sse", "--header", "bearer:${BEARER}" ], "env": { "BEARER": "YOUR_LATITUDE_API_KEY" } } } } ``` **VS Code (Copilot)** Open the Command Palette → **MCP: Open User Configuration** and add: ```json theme={null} { "servers": { "Latitudesh": { "command": "npx", "args": [ "-y", "mcp-remote@latest", "https://mcp.latitude.sh/sse", "--header", "bearer:${BEARER}" ], "env": { "BEARER": "YOUR_LATITUDE_API_KEY" } } } } ``` Restart VS Code and enable Agent mode in Copilot Chat. **Windsurf** Go to **Settings → Cascade → Manage MCPs → View raw config** and add: ```json theme={null} { "mcpServers": { "Latitudesh": { "command": "npx", "args": [ "-y", "mcp-remote@latest", "https://mcp.latitude.sh/sse", "--header", "bearer:${BEARER}" ], "env": { "BEARER": "YOUR_LATITUDE_API_KEY" } } } } ``` **Codex** Add to your Codex configuration (replace `YOUR_LATITUDE_API_KEY`): ```toml theme={null} [mcp_servers.Latitudesh] url = "https://mcp.latitude.sh/sse" http_headers = { "bearer" = "YOUR_LATITUDE_API_KEY" } ``` **Claude Desktop** One-click install via the MCP bundle: **1. Download the bundle** Get `mcp-server.mcpb` from the [GitHub releases](https://github.com/latitudesh/latitudesh-mcp/releases). **2. Open Extensions** In Claude Desktop, go to **Settings → Extensions**. **3. Install** Drag the bundle onto the Extensions page and follow the prompts. > [!NOTE] > > For any key-based client not listed above, use the same `mcp-remote` > configuration shown in the tabs: run `npx -y mcp-remote@latest > https://mcp.latitude.sh/sse --header bearer:${BEARER}` and keep your API key > in a `BEARER` env var rather than inlining it. ## What you can do Be explicit in your prompts (e.g. *"List my servers on Latitude.sh"*) so the agent uses the MCP tools rather than searching locally. * 🔎 List and inspect servers, projects, SSH keys, and events * ⚙️ Create, reinstall, lock, or delete bare-metal servers * 🖥️ Manage virtual machines and Kubernetes clusters * 💾 Provision block, filesystem, and object storage * 📡 Configure private networks, VPN sessions, elastic IPs, and firewalls * 👥 Manage teams, members, roles, tags, and API keys * 📊 Check traffic, bandwidth, and billing usage The server exposes tools across **API Keys, Billing, Servers, Virtual Machines, Kubernetes, Projects, SSH Keys, Storage, Private Networks, VPN Sessions, Elastic IPs, IP Addresses, Firewalls, Plans, Regions, Roles, Tags, Teams, Traffic, User Data, and Events**. ## Contributing The Latitude.sh MCP server is open source. Visit the [GitHub repository](https://github.com/latitudesh/latitudesh-mcp) to open issues or submit pull requests. # Postman Collection Source: https://www.latitude.sh/docs/development/postman Test and explore the Latitude.sh API using Postman The Latitude.sh Postman Collection provides a convenient way to test and explore the API endpoints directly from Postman. > **[Postman Collection](https://www.postman.com/latitudesh/workspace/latitude-sh-developers/overview)** ## Getting Started 1. **Import the collection** into your Postman workspace 2. **Set up authentication** by adding your API key to the collection variables 3. **Start making requests** to explore the Latitude.sh API ## What's Included The collection includes pre-configured requests for: * Server management (deploy, list, update, delete) * Virtual machines * Networking (VLANs, IP addresses) * Storage and databases * Projects and teams * And more... ## API Keys You'll need an API key to authenticate your requests. Generate one from your [dashboard](https://www.latitude.sh/dashboard/api-keys). # Terraform Source: https://www.latitude.sh/docs/development/terraform # Activity logs Source: https://www.latitude.sh/docs/events Activity logs enhance visibility and traceability for actions and activities performed on the platform. It helps you meet your security and compliance requirements, provide real-time tracking, and increases your visibility about actions your team performs. #### API Fetch activity logs using the [Events API](https://www.latitude.sh/docs/api-reference/get-events). #### Dashboard Go to **Settings** and then click **Activity** on the left sidebar to see your account activity logs. ![Activity logs on the Latitude.sh dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/36.Docs25Q4.ActivityLogs.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=fac0a08da5c368770645727eef0f2e2b) # Examples Source: https://www.latitude.sh/docs/examples Code examples for common use cases ## Code Examples Repository Visit our **[Examples Repository on GitHub](https://github.com/latitudesh/examples)** for practical code examples. > **[Custom Images](https://github.com/latitudesh/examples/tree/main/custom-images)** > > Deploy custom Operating System images using iPXE > **[Terraform](https://github.com/latitudesh/examples/tree/main/terraform)** > > Deploy complex infrastructure using the Terraform provider > **[User Data](https://github.com/latitudesh/examples/tree/main/user-data)** > > Use cloud-init to run code on your servers on first boot > **[Storage](https://github.com/latitudesh/examples/tree/main/storage)** > > Examples for working with block storage and filesystems > [!NOTE] > > We welcome contributions! Feel free to open issues or submit pull requests > with new examples. # Guides Source: https://www.latitude.sh/docs/guides Tutorials to help you deploy and manage workloads on Latitude.sh Welcome to the guides section of the Latitude.sh documentation. Here, you'll find a variety of tutorials and examples to help you get the most out of our platform. We built these guides with the following principles in mind: * **No kitchen-sink**: We only write about what we genuinely believe is good for production use cases. You won't find guides for everything that can be deployed on Latitude.sh, but for software and patterns that can scale with you, that we use ourselves, and that have been battle-tested across multiple customers and use cases. * **No "use Latitude.sh to" hype**: We believe in being honest about what Latitude.sh can and cannot do and will not try to sell you on the idea that you should use Latitude.sh for everything. * **No unnecessary complexity**: We avoid unnecessary complexity and focus on the essentials. # Introduction to Kubernetes Source: https://www.latitude.sh/docs/guides/introduction-to-kubernetes Understanding Kubernetes on bare metal infrastructure and why it's essential for modern application deployment ## Introduction Kubernetes is a container orchestrator designed for applications that run on containers and need the following things: * Service Discovery and Load Balancing * Automatic Bin Packing * Storage Orchestration * Self Healing * Secret and Configuration Management * Automated Rollouts and Rollbacks * Batch Execution * Horizontal Scaling Kubernetes is used in production environments running applications that should be available at all times, with a lot of variables to monitor. Kubernetes is also known as K8s and is a big tool with many fancy knobs and buttons, and this article will try to explain and demystify some basics of what Kubernetes is. ## Why you should use it In the general process of deploying applications, we encounter various issues with the way we want to get it working. One problem with deploying applications in production before Kubernetes and other container orchestrators was the problem of managing resources. We had to spin up a server to deploy a new application. A server, in principle, should only hold one application, including all of its dependencies, which would have to be manually deployed via some CI process every time we wanted to use it. This process was very stressful and required many technical skills to manage various things such as networking, security, storage, and all that would go to waste if the server became unresponsive and stopped working due to various factors. ## Why Containers Containers provide a good isolation level between the application and the machine running it. If the container running the application goes down, it doesn't affect the machine. Since this is the case, we can spin up several containers on a single machine without hoping for conflict. Kubernetes provides this container management feature and the ability to run multiple servers in a cluster setup. Kubernetes can control these multiple machines by running a Control Plane, which defines how the master and slaves communicate with each other. > The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. > > The Control Plane maintains a record of all of the Kubernetes Objects in the system and runs continuous control loops to manage those objects' states. > > At any given time, the Control Plane's control loops will respond to changes in the cluster and work to make the actual state of all the objects in the system match the desired state that you provided. > > Source: [https://kubernetes.io/docs/concepts/#kubernetes-objects](https://kubernetes.io/docs/concepts/#kubernetes-objects) ## Kubernetes Architecture There are two cluster types in Kubernetes since it is generally for handling distributed workloads: * Master * Slaves ### Master This is what we use to talk to the slaves. In Kubernetes, the master is the one we communicate about what deployments should be on our cluster and how they should be managed. The master delegates work to the slaves, who are responsible for starting the containers and ensuring they function as desired. The master does this using a collection of three processes: * API server (kube-apiserver) * Controller manager (kube-controller-manager) * Scheduler (kube-scheduler) The **API server** is what we use to perform duties from a client. The control plane is accessible to the outside world via this API server. From here, we can perform various operations inside and outside of the cluster using a client tool called Kubernetes Control (KubeCtl). The **Controller manager** does all the checking and validation of the task we sent to the cluster using the API server. So things like making sure our deployment doesn't fail and that the general health of the cluster and things running on it are in great shape. It does this by continuously checking different resource objects on Kubernetes to ensure they function as expected. The **Scheduler** is what enforces rules on the cluster. In Kubernetes, because we run many applications in different containers, we do not want just one to take over all the resources like RAM, CPU, and Storage and undermine others. The Scheduler is, therefore, the one that schedules these checks and ensures that any application joining on any slave can fit there, and if not, schedules it to another so that the workload on any slave is fairly shared amongst all of them. ### Slaves These nodes do the grunt work of running services and all the applications needs. The Scheduler is the one that pushes the requests to them, and they are then monitored by the controller manager and interacted with by us through the API Server over the master. In general, the slaves run two things: * Kubelet * Kube-Proxy **Kubelet** is responsible for talking with the master node. It's what the master node uses to communicate and perform various actions, such as scheduling and monitoring. **Kube-proxy** exposes the applications on the node. Just as Kubelet communicates with the master, kube-proxy communicates with the applications. Kube-proxy exposes the ports from the containers running to the outside world using *Services*. ## Containers in Kubernetes ![Containers running on bare metal vs VMs](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/619503c-vm_vs_con_sbj57m.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=a1eeab533bd551788083d22aa1ee96fa) We use containers because they allow us to run multiple applications on a single host machine. This is because containers run in sandboxes, making them more secure. After all, only the host can see them without one container being able to see or interfere with another. This is impossible if we ran all our applications on a single server. ## Deployments and Containers In Kubernetes, because we have different things like Networking, Storage, RAM, and CPU to manage amongst various applications that might or might not be similar, we interact with these various resources using Kubernetes Objects. > Kubernetes contains several abstractions that represent the state of your system: deployed containerized applications and workloads, their associated network and disk resources, and other information about what your cluster is doing. > > These abstractions are represented by objects in the Kubernetes API > > Source: [https://kubernetes.io/docs/concepts/#kubernetes-objects](https://kubernetes.io/docs/concepts/#kubernetes-objects) The basic Kubernetes objects include: * **Pod** - Running Application * **Service** - Networking and Port Allocation * **Volume** - Storage and Disk Management * **Namespace** - Sandbox For Running Multiple Versions Also, Kubernetes contains several higher-level abstractions called Controllers. Controllers build upon the basic objects and provide additional functionality and convenience features. They include: * **ReplicaSet** - Similar Pods Running Together * **Deployment** - A higher group built on a collection of Pods which may or may not be similar * **StatefulSet** - An application that has Volume requirements and should not start unless it is offered a separate and persistent space to store files * **DaemonSet** - Just like a ReplicaSet, but this one should be present on all nodes running in the cluster * **Job** - A short-running Pod, good for things like webhooks and email dispatchers These and much more are the different types of Kubernetes objects. Filtering through all the big talk, we will only focus on deployments. As earlier stated, a deployment is a collection of one or more pods that may or may not be similar depending on the task it is meant to accomplish. A pod is a running container that has been allocated resources. A pod on its own is never a good idea as it has limited functionality and cannot restart itself once it dies or an error occurs. Deployments and various higher-order groups built on Pods allow us to run a certain number and keep a minimum number going so that our application never dies, even under the influence of a failed pod. ## Exposing a Deployment With Services ![Kubernetes Service Pods](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/a3ac03a-bak2_ndewpp.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=8960907c2200844d9af49d4f69959431) Just as a deployment runs one or more pods, we have to think about how to access it. When we deploy applications, they are often accessible from a browser or client through a Port. The Port allows us to access multiple services on the same machine without worrying about conflict; a service allows us to access a deployment spread across different machines without worrying about where it is running. This is made possible by the `kube-proxy` which can forward our request to the machine where it is deployed and send the response back through that same channel. # Deploy custom OS via IPMI virtual media Source: https://www.latitude.sh/docs/guides/ipmi-custom-os-deployment Step-by-step guide for installing custom operating systems using IPMI virtual media mounting This comprehensive guide walks you through deploying a custom operating system on your Latitude.sh bare metal server using IPMI (Intelligent Platform Management Interface) virtual media. This method provides a reliable alternative to iPXE scripts when you need to install custom operating systems that aren't available in our standard image catalog. ## What you'll learn By the end of this guide, you'll be able to: * Access and configure IPMI virtual media functionality * Mount custom ISO files remotely via IPMI * Boot from virtual media and complete OS installations * Troubleshoot common IPMI deployment issues ## Prerequisites Before starting this guide, ensure you have: * **A Latitude.sh bare metal server** with IPMI access enabled * **Custom OS ISO file** downloaded and accessible on your local machine * **Java Runtime Environment** installed on your local machine (required for IPMI console) * **VPN access** configured for [Remote Access](/docs/servers/remote-access) * **Basic familiarity** with server boot processes and OS installation ## Step 1: Prepare your custom OS ISO First, download and prepare your custom operating system ISO file: 1. **Download your ISO**: Obtain the custom OS ISO file and save it to an easily accessible location on your local machine 2. **Verify the ISO**: Ensure the ISO file is not corrupted by checking its hash if provided by the OS vendor 3. **Note the file path**: Make a note of the complete file path as you'll need it during the mounting process > 💡 **Tip**: Place the ISO file in a directory without spaces in the path to avoid potential issues with the IPMI interface. ## Step 2: Configure VPN access (if required) **Important**: IPMI interfaces are typically only accessible from within the data center's secure network. Depending on your server's configuration and location, you may need VPN access to reach the IPMI interface. ### When VPN access is required VPN access may be required if: * Your server is configured with restricted IPMI network access * Your location requires secure tunnel access to management interfaces * You're accessing IPMI from outside the data center's trusted network range ### Setting up VPN access If VPN access is required for your server: 1. **Contact Latitude.sh support** to request VPN access credentials for your server's location 2. **Provide the following information**: * Your server hostname or ID * The specific location/data center * Business justification for IPMI access * Your public IP address for allowlisting (if applicable) 3. **Configure your VPN client** with the provided credentials: * Install your preferred VPN client (OpenVPN, WireGuard, etc.) * Import the configuration file provided by support * Connect to the VPN before attempting IPMI access 4. **Verify connectivity**: Once connected to the VPN, you should be able to access the IPMI interface through the dashboard > 📝 **Note**: VPN requirements vary by location and server configuration. Some servers may have IPMI interfaces accessible directly through the dashboard without additional VPN setup. ## Step 3: Access your server's IPMI interface Navigate to your server's management interface: 1. **Ensure VPN connection** (if required): Verify your VPN connection is active before proceeding 2. **Open the Latitude.sh dashboard** and locate your target server 3. **Generate IPMI credentials**: * Click on your server to open its details page * Navigate to the **Remote Access** section * Click **Generate IPMI credentials** to create temporary access credentials * Copy the provided username and password 4. **Access the IPMI interface**: * Click **Access the IPMI** to open the IPMI web interface in your browser * Log in using the credentials from the previous step For detailed instructions on accessing IPMI, refer to our [Remote Access documentation](/docs/servers/remote-access). ## Step 4: Configure the IPMI console for Java **Critical step**: The virtual media functionality requires the Java console, not the HTML5 version. 1. **Locate console settings**: In the IPMI interface, look for **Console** or **Remote Console** options 2. **Select Java console**: * Find the console type or launch options * Ensure **Java** is selected instead of HTML5 * Some IPMI interfaces may label this as "Java Web Start" or "JViewer" 3. **Configure Java security** (if prompted): * Add the IPMI URL to your Java security exceptions * Allow Java to run when prompted by your browser * You may need to download and run a `.jnlp` file > ⚠️ **Important**: Virtual media functionality is not available in HTML5 console mode. You must use the Java console for this procedure. ## Step 5: Launch the Java console 1. **Start the console**: Click the appropriate button to launch the Java console (may be labeled "Launch Console", "Java Console", or similar) 2. **Wait for initialization**: The console may take 30-60 seconds to fully load 3. **Verify connection**: You should see a remote desktop view of your server's current state If the console fails to load, check your Java installation and browser security settings. ## Step 6: Mount your ISO using virtual media Now you'll mount your custom ISO file: 1. **Access Virtual Media**: * In the Java console window, locate the **Virtual Media** menu (usually in the top menu bar) * Click on **Virtual Media** or **Virtual Storage** 2. **Configure the virtual drive**: * Select **ISO Image** as the Logical Drive Type * Click **Browse** or **Choose File** to select your ISO * Navigate to and select your custom OS ISO file 3. **Mount the ISO**: * After selecting the file, click **Plug In** or **Connect** * Verify that the status shows as "Connected" or "Plugged In" * The virtual media should now appear as an available boot device > 📝 **Note**: Some IPMI interfaces may show the mounted ISO as "Virtual CDROM", "Virtual DVD", or similar in the boot options. ## Step 7: Reboot and access the boot manager Time to boot from your mounted ISO: 1. **Reboot your server**: * You can reboot through the IPMI power controls in the console * Alternatively, use the power management options in the Latitude.sh dashboard * Or execute `sudo reboot` if you have SSH access 2. **Enter Boot Manager**: * **Watch the boot process** carefully through the Java console * **Press F11** repeatedly as the server starts up (timing is crucial) * You may need to press F11 multiple times or hold it down * Some servers may use F12, F8, or Delete instead of F11 3. **Alternative boot access**: * If F11 doesn't work, try other common boot keys during startup * Check your server's documentation for the specific boot key * Some systems require pressing the key immediately after the POST screen ## Step 8: Boot from virtual CDROM In the Boot Manager menu: 1. **Locate virtual media**: Look for options like: * "Virtual CDROM" * "Virtual DVD" * "IPMI Virtual Media" * "USB CDROM" (some systems show virtual media this way) 2. **Select the virtual drive**: * Use arrow keys to highlight the virtual CDROM option * Press **Enter** to select it * The system should begin booting from your mounted ISO 3. **Monitor the boot process**: Watch the console as your custom OS begins to load ## Step 9: Complete the OS installation Your custom operating system should now boot into its installation environment: 1. **Follow OS-specific prompts**: Each operating system has its own installation process 2. **Configure network settings**: Set up networking according to your server's configuration 3. **Partition disks**: Configure storage according to your requirements 4. **Complete installation**: Follow through with the full OS installation process **Installation considerations**: * **Keep the console active**: Don't close the Java console during installation * **Monitor progress**: Some installations may appear to hang but are actually processing * **Respond to prompts**: Be ready to interact with installation dialogs * **Installation time**: Custom OS installations can take 30 minutes to several hours ## Step 10: Post-installation cleanup After successful installation: 1. **Disconnect virtual media**: * Return to the Virtual Media menu in the Java console * Click **Plug Out** or **Disconnect** to unmount the ISO * This prevents the server from trying to boot from the ISO again 2. **Reboot the server**: Restart to boot into your newly installed OS 3. **Verify installation**: Confirm your custom OS is running correctly 4. **Configure remote access**: Set up SSH or other remote access methods as needed ## Troubleshooting common issues ### Java console problems **Console won't load or crashes**: * Ensure Java is installed and up to date on your local machine * Add the IPMI URL to Java security exceptions * Try using a different browser * Clear Java cache and temporary files **Virtual Media menu missing**: * Confirm you're using the Java console, not HTML5 * Check if your user account has virtual media permissions * Try refreshing the console connection ### Boot manager issues **F11 not working**: * Try F12, F8, Delete, or Esc during boot * Press the key repeatedly rather than holding it down * Check server documentation for the correct boot key * Ensure you're pressing the key at the right time (usually right after POST) **Virtual CDROM not visible**: * Verify the ISO is properly mounted and shows as "Connected" * Try disconnecting and reconnecting the virtual media * Reboot the server and try again * Check if the ISO file is corrupted ### Installation problems **Network connectivity issues**: * Verify your server's network configuration * Check if the custom OS includes necessary network drivers * Configure static IP if DHCP isn't working **Storage not detected**: * Your custom OS may need specific storage drivers * Check if RAID configuration is compatible * Try different storage controller modes in BIOS if accessible **Installation hangs or fails**: * Monitor system resources during installation * Check console for error messages * Verify ISO file integrity * Try a different version of the OS if available ## Alternative deployment methods If IPMI virtual media doesn't work for your use case, consider these alternatives: * **[iPXE custom images](/docs/servers/custom-images)**: Network-based deployment using custom boot scripts * **[Rescue mode](/docs/servers/rescue-mode)**: Manual installation using a rescue environment * **[Standard OS images](/docs/servers/operating-systems)**: Check if your desired OS is available in our catalog ## Best practices and tips * **Test your ISO**: Verify the ISO works in a virtual machine before using IPMI * **Document your process**: Keep notes of successful configurations for future deployments * **Plan for time**: Allow several hours for the complete process * **Monitor actively**: Stay engaged during the installation process * **Backup configurations**: Save working IPMI and OS configurations ## Getting help If you encounter issues during IPMI custom OS deployment: 1. **Gather information**: * Screenshots of error messages * Details about your custom OS and ISO file * Description of the specific step where issues occur * Server model and IPMI firmware version 2. **Contact support**: Our technical team can help with: * IPMI-specific configuration issues * Boot manager problems * Hardware compatibility questions * Alternative deployment strategies ## Conclusion You've successfully learned how to deploy custom operating systems using IPMI virtual media. This method provides a reliable way to install any OS that can boot from ISO media, giving you complete control over your server's software environment. The IPMI virtual media approach is particularly valuable for: * Installing specialized or proprietary operating systems * Deploying custom-configured OS images * Situations where network-based deployment isn't feasible * Maintaining complete control over the installation process With this knowledge, you can now deploy virtually any operating system on your Latitude.sh bare metal servers, opening up possibilities for specialized workloads and custom configurations that aren't available through standard deployment methods. # Monitoring a Kubernetes cluster on bare metal with Prometheus and Grafana Source: https://www.latitude.sh/docs/guides/k8s-monitoring Get real-time visibility into your cluster's health and performance After [deploying your Kubernetes cluster on bare metal](/docs/guides/kubernetes-on-bare-metal), it's important to set up monitoring to track its health and performance. This guide walks you through installing and configuring [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) to collect metrics, visualize data, and set up alerts for your Kubernetes environment. Let's get started! ## Prerequisites * A running Kubernetes cluster. * `kubectl` configured. * `Helm 3` installed on your local machine. Verify your cluster is ready: ```shell theme={null} kubectl cluster-info ``` ## Step 1: Add the Prometheus Helm repository ```bash theme={null} helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update ``` ## Step 2: Install the Prometheus stack Install everything (Prometheus, Grafana, Alertmanager) with one command: ```bash theme={null} helm install monitoring prometheus-community/kube-prometheus-stack ``` This uses default settings and creates a full monitoring stack. ## Step 3: Verify installation **1. Check pods status** Check if all pods are running: ```bash theme={null} kubectl get pods ``` You should see the pods of the monitoring stack running: ```bash theme={null} > kubectl get pods -n monitoring NAME READY STATUS RESTARTS AGE alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 53s kube-prometheus-stack-grafana-76649cf75d-r4x7k 3/3 Running 0 3m6s kube-prometheus-stack-kube-state-metrics-77899fc47f-xmkhf 1/1 Running 0 3m6s kube-prometheus-stack-operator-6b6c6f966d-hrsjk 1/1 Running 0 3m6s kube-prometheus-stack-prometheus-node-exporter-dcwzq 1/1 Running 0 3m6s prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 3m6s ``` **2. Check services** Check the services: ```bash theme={null} kubectl get services -n monitoring ``` This will show the created services for the monitoring stack and their assigned IPs. ## Step 4: Access the Grafana dashboard By default, Grafana is only accessible from within the cluster. Use port forwarding to view it locally. **1. Set up port forwarding** Run the following command to forward the port: ```bash theme={null} kubectl port-forward svc/kube-prometheus-stack-grafana -n monitoring 3000:80 ``` **2. Open Grafana** Open [http://localhost:3000](http://localhost:3000/) in your browser. **3. Login with default credentials** Log in with the default credentials: * **Username:** admin * **Password:** prom-operator ![Grafana login screen](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/k8s-monitoring/grafana-login-localhost.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=469a5300a0d55d5536deb36364096acf) If you need to retrieve the password: ```bash theme={null} kubectl get secret kube-prometheus-stack-grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode; echo ``` ## Step 5: Confirm Prometheus as a data source The `kube-prometheus-stack` automatically sets up Prometheus as a data source in Grafana. To check: **1. Login to Grafana** Login to Grafana. **2. Go to Data Sources** Go to **Connections > Data Sources**. **3. Confirm Prometheus** Confirm Prometheus is listed. ![Grafana data sources](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/k8s-monitoring/grafana-data-sources.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=f75b869b52a8440ef898134eb6fd3431) ## Step 6: Explore dashboards Grafana includes several pre-built dashboards out of the box. To access them: **1. Navigate to dashboards** Click **Dashboards** in the sidebar. **2. Browse available dashboards** Select **Browse**. For a high-level overview, start with **Kubernetes / Compute Resources / Cluster**. This dashboard provides insights into: * Overall cluster CPU, memory, and filesystem usage. * Pod and container performance. * System service metrics. ![Grafana Kubernetes dashboard](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/k8s-monitoring/grafana-dashboard.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=ede1d8b50b3025a3e834c0709d893f2a) ## Step 7: Set up basic alerts `Alertmanager` is already included as part of the `kube-prometheus-stack`. To manage alerts: **1. View alerts** In Grafana, go to **Alerting > Alert Rules**. View existing alerts or create new ones. **2. Configure contact points** To receive alerts: Go to **Alerting > Contact points**. Click **Create contact point**. Set up notifications (email, Slack, etc.). ![Grafana contact points](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/k8s-monitoring/grafana-contact-points.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=935b942903727a7e1f2871e3a1858753) ## Done! You now have a working monitoring setup for your Kubernetes cluster. For advanced dashboards or deeper integration, check out the [Prometheus](https://prometheus.io/docs/) and [Grafana](https://grafana.com/docs/) documentation. # Kubernetes cluster with RKE2 Source: https://www.latitude.sh/docs/guides/kubernetes-cluster-rke2 Step-by-step setup for building a reliable Kubernetes environment on bare metal Developed in collaboration with [eOracle](https://www.latitude.sh/customers/eoracle), this guide will walk you through the process of setting up a K8s cluster on bare metal using [RKE2](https://docs.rke2.io/). RKE2 (Rancher Kubernetes Engine 2) is a lightweight, secure, and production-ready Kubernetes distribution designed to simplify cluster deployment and management. Let's dive in! ## Prerequisites * [Latitude.sh servers](https://www.latitude.sh/dashboard) (at least 3 control-plane nodes and 2 worker nodes). * [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) installed on your local machine. * A DNS A-record pointing to the control-plane nodes. * Properly configured IP addresses for all nodes. * SSH access to all nodes with `root` privileges. * A `server token `and `agent token` to securely join nodes to the cluster. * [Cilium](https://cilium.io/) as the CNI plugin ## Step 1: Prepare DNS and generate tokens **1. Set up DNS record** Set up a DNS A-record that points to the external IP addresses of all control-plane nodes. This record will serve as the Kubernetes API endpoint and the RKE2 registration address. **2. Generate tokens** Run the following command twice to create a server-token (for control-plane nodes) and an agent-token (for worker nodes): ```shell theme={null} openssl rand -hex 32 ``` Save both tokens for use during the cluster setup. ## Step 2: Configure RKE2 on the first control-plane node On the first server, create the RKE2 configuration file at `/etc/rancher/rke2/config.yaml` with the following content: ```shell theme={null} token: agent-token: tls-san: - rke2.ext.example.com - node-name: control-plane-01 advertise-address: node-ip: node-external-ip: disable: - rke2-ingress-nginx cni: "cilium" disable-kube-proxy: true ``` Replace `` and `` with the generated tokens. ## Step 3: Install RKE2 **1. Set RKE2 version** Set the desired [RKE2 version](https://github.com/rancher/rke2/releases) as an environment variable: ```shell theme={null} export RKE2_VERSION=v1.31.1+rke2r1 ``` **2. Install RKE2 server** Run the following command to install the RKE2 distribution on the first control-plane node: ```shell theme={null} curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=${RKE2_VERSION} INSTALL_RKE2_TYPE=server INSTALL_RKE2_CHANNEL=stable INSTALL_RKE2_METHOD=tar sh - ``` **3. Start RKE2 service** Enable RKE2 to start on boot, start the service, and observe the service logs: ```shell theme={null} systemctl enable rke2-server.service && systemctl restart rke2-server.service & journalctl -u rke2-server -f ``` ## Step 4: Configure additional control-plane nodes **1. Get tokens from first node** After deploying the first control-plane node, use the tokens located at `/var/lib/rancher/rke2/server` as the server token and `/var/lib/rancher/rke2/server/agent-token` as the agent token. > [!NOTE] > > The `server` option applies to all nodes except the first. **2. Configure additional control-plane nodes** Create the configuration file `/etc/rancher/rke2/config.yaml` on each additional control-plane node. Example for `control-plane-02`: ```shell theme={null} server: https://rke2.ext.example.com:9345 token: agent-token: tls-san: - rke2.ext.example.com - node-name: control-plane-02 advertise-address: node-ip: node-external-ip: disable: - rke2-ingress-nginx cni: "cilium" disable-kube-proxy: true ``` Example for `control-plane-03`: ```shell theme={null} server: https://rke2.ext.example.com:9345 token: agent-token: tls-san: - rke2.ext.example.com - node-name: control-plane-03 advertise-address: node-ip: node-external-ip: disable: - rke2-ingress-nginx cni: "cilium" disable-kube-proxy: true ``` Repeat this process for all control-plane nodes, updating the node-name and IP addresses accordingly. **3. Configure worker nodes** Install agent nodes and create the following configuration file at `/etc/rancher/rke2/config.yaml`: ```shell theme={null} server: https://rke2.ext.example.com:9345 token: node-name: worker-node-01 node-ip: node-external-ip: node-label: - "node.kubernetes.io/role=worker" ``` **4. Install RKE2 agent** Run `export RKE2_VERSION=v1.31.1+rke2r1` Install the RKE2 distribution: ```shell theme={null} curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION=${RKE2_VERSION} INSTALL_RKE2_TYPE=agent INSTALL_RKE2_CHANNEL=stable INSTALL_RKE2_METHOD=tar sh - ``` Enable RKE2 to start on boot, start the service, and observe the service logs: ```shell theme={null} systemctl enable rke2-agent.service && systemctl restart rke2-agent.service & journalctl -u rke2-agent -f ``` ## Step 5: Acquire the kubeconfig file **1. Locate kubeconfig** Locate the kubeconfig file on any control-plane node at `/etc/rancher/rke2/rke2.yaml.` The file should look similar to this: ```shell theme={null} apiVersion: v1 clusters: - cluster: certificate-authority-data: server: https://127.0.0.1:6443 name: default contexts: - context: cluster: default user: default name: default current-context: default kind: Config preferences: {} users: - name: default user: client-certificate-data: client-key-data: ``` **2. Update server address** Replace the server value with the external registration address: `server: https://rke2.ext.example.com:6443` **3. Copy to local machine** Copy the file to your local machine and save it as `~/.kube/config` or another location (e.g., `~/.kube/test`). Use the following command to check the cluster nodes: ```shell theme={null} kubectl get nodes --kubeconfig ~/.kube/test ``` ## Step 6: Configure Cilium for kube-proxy replacement **1. Create Cilium configuration** Create a file named `rke2-cilium-values.yaml`with this content: ```shell theme={null} apiVersion: helm.cattle.io/v1 kind: HelmChartConfig metadata: name: rke2-cilium namespace: kube-system spec: valuesContent: |- k8sServiceHost: "rke2.ext.example.com" k8sServicePort: "6443" kubeProxyReplacement: "true" ``` > [!NOTE] > > You must specify `KUBERNETES_SERVICE_HOST` and `KUBERNETES_SERVICE_PORT` in the configuration to enable kube-proxy replacement mode. See the [HelmChartConfig](https://docs.rke2.io/helm#customizing-packaged-components-with-%20helmchartconfig) for more information. **2. Apply configuration** Run this command to apply the configuration: ```shell theme={null} kubectl apply -f ./rke2-cilium-values.yaml --kubeconfig ~/.kube/test ``` Check if the configuration is applied: ```shell theme={null} helmchartconfig.helm.cattle.io/rke2-cilium created ``` Cilium is now configured to replace kube-proxy. ## Step 7: Check cluster status **1. Check pod status** Run the following to check the status of all pods in all namespaces: ```shell theme={null} kubectl get pods -A --kubeconfig ~/.kube/test ``` Ensure all pods are in the **Running** state. **2. Check node status** Check the status of all nodes: ```shell theme={null} kubectl get nodes --kubeconfig ~/.kube/test ``` Nodes should show **Ready** in the Status column. ## Troubleshooting Add these aliases to perform troubleshooting on control-plane nodes: ```shell theme={null} alias kubectl='/var/lib/rancher/rke2/bin/kubectl --kubeconfig /etc/rancher/rke2/rke2.yaml' kubectl get nodes alias crictl='/var/lib/rancher/rke2/bin/crictl' export CONTAINER_RUNTIME_ENDPOINT="unix:///run/k3s/containerd/containerd.sock" crictl ps ``` ## That's it! Your cluster is now set up and ready to handle workloads on bare metal. Check out our guide on [Kubernetes load balancing](/docs/guides/kubernetes-load-balancing-on-bare-metal) to optimize traffic management across your nodes. # Load balancing with MetalLB and Cloudflare Source: https://www.latitude.sh/docs/guides/kubernetes-load-balancing-on-bare-metal Set up a load balancer to distribute incoming traffic to the apps running on your Kubernetes cluster The instructions here should work for any Kubernetes distro running on bare metal. If you don't have a cluster yet, start by [deploying one](/docs/guides/kubernetes-on-bare-metal). *** Running a Kubernetes cluster on bare metal is great, but you need a way to distribute incoming traffic to your applications. This is where a load balancer comes in. A load balancer is a service that distributes incoming network traffic across multiple servers. It ensures that no single server becomes overwhelmed with traffic, and it can help improve the performance and reliability of your applications. In this guide, we'll show you how to set up a load balancer for your Kubernetes cluster on bare metal. We'll use Cloudflare for DNS and load balancing, but you can use any load balancer you want, like Nginx or HAProxy. ## Requirements * [Cloudflare account](https://dash.cloudflare.com) for DNS and load balancing * [Kubernetes cluster](/docs/guides/kubernetes-on-bare-metal) deployed on Latitude.sh ## Getting started To distribute traffic to the applications on your Kubernetes cluster, you first need to expose a service that acts as a load balancer — note that this is different from the load balancer we'll set up for DNS. For bare metal, [MetalLB](https://metallb.universe.tf/) is a great option. MetalLB is a stable and reliable service for Kubernetes load balancing. Let's get started. ## Install MetalLB **1. Install with Helm** Use Helm to install MetalLB. Refer to MetalLB's [installation guide](https://metallb.universe.tf/installation/#installation-with-helm) for up to date instructions. **2. Create an IPAddressPool** An `IPAddressPool` is a range of IP addresses that MetalLB will use to assign IP addresses to the load balancer services. You can use your own server's IP addresses or [get additional IPs](/docs/networking/ips#additional-ips) if you prefer. The IPAddressPool requires an IP range, but we can also add the IPs of our worker nodes, which isn't the best for a production environment but not a different process from doing with additional IPs. So let's say our Kubernetes worker nodes IPs are `160.202.129.150`, `160.202.145.233`, and `197.187.133.133`. Make note of these IPs and create a file named `ipaddresspool.yaml` on your local machine. Each Latitude.sh server has its own /31 VLAN, so we need to create an IPAddressPool for each server. Make sure to replace the IP addresses with the IPs of your worker nodes. ```yaml theme={null} apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: first-pool namespace: metallb-system spec: addresses: - 160.202.129.150-160.202.129.150 --- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: second-pool namespace: metallb-system spec: addresses: - 160.202.145.233-160.202.145.233 --- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: third-pool namespace: metallb-system spec: addresses: - 197.187.133.133-197.187.133.133 ``` Then apply to your cluster. ```sh theme={null} kubectl apply -f ipaddresspool.yaml ``` **3. Create L2Advertisements** After creating the IPAddressPool, we need to create an L2Advertisement to announce the IP addresses to the network. Create a file named `l2advertisement.yaml` with the following content. ```yaml theme={null} apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: first-pool-advertisement namespace: metallb-system spec: ipAddressPools: - first-pool nodeSelectors: - matchLabels: kubernetes.io/hostname: node1 apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: second-pool-advertisement namespace: metallb-system spec: ipAddressPools: - second-pool nodeSelectors: - matchLabels: kubernetes.io/hostname: node2 apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: third-pool-advertisement namespace: metallb-system spec: ipAddressPools: - third-pool nodeSelectors: - matchLabels: kubernetes.io/hostname: node3 ``` And apply it ```sh theme={null} kubectl apply -f l2advertisement.yaml ``` **4. Make sure everything is working** To make sure everything is working, you can create a service and a deployment and see if the load balancer is distributing traffic to the pods. Here's an example of a service and a deployment for nginx. ```yaml theme={null} apiVersion: v1 kind: Service metadata: name: my-service spec: type: LoadBalancer selector: app: MyApp ports: - protocol: TCP port: 80 targetPort: 80 ``` If everything is working, you should be able to access the service from outside the cluster by visiting the IP address of the load balancer. ## Setup Cloudflare DNS Now that we have a load balancer, we need to set up Cloudflare DNS to point to the load balancer. We have two options: 1. Create a DNS record that points to all the IPs of the load balancer. 2. Create a DNS record through Cloudflare's load balancer service. For the purpose of this guide, we'll go with the second option. **1. Create load balancer service** From your Cloudflare dashboard, go to the **Traffic > Load Balancing** section and click on "Create Load Balancer". **2. Set the load balancer settings** * Hostname: choose a hostname for your service. E.g., `k8s-guide.my-domain.com`. * Endpoints: create and add a pool with the IPs of your Kubernetes worker nodes. You don't need a fallback pool. Everything else is optional and can be changed later to your liking. ## That's it! You should now be able to access services from outside the cluster with MetalLB as the load balancer for application traffic and Cloudflare for DNS. # Kubernetes on bare metal with Rancher Source: https://www.latitude.sh/docs/guides/kubernetes-on-bare-metal A guide to get you started with Kubernetes on bare metal with Rancher RKE2 Managed Kubernetes is the go-to way to get started with Kubernetes. EKS, GKE, and AKS are all popular Kubernetes services. You give away control in exchange for a faster setup. As your Platform team matures and your workloads grow, you might want to run Kubernetes on infrastructure you control for cost, control, or performance purposes. Or you may have realized that the added lock-in of managed Kubernetes is not worth it. Either way, running Kubernetes on bare metal is a great option. You get the control and performance of running on infrastructure you control without the overhead of virtualization. So we did the heavy lifting for you. A guide and Terraform plan to get Kubernetes up and running on bare metal. ## Requirements * [1 Latitude.sh](https://www.latitude.sh) server for Rancher * [3 Latitude.sh](https://www.latitude.sh) servers for the cluster * [Kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and [helm](https://helm.sh/docs/intro/install/) installed on your local machine for managing the cluster ## Let's get started We have tried and tested most Kubernetes services, control planes and distributions. [Rancher RKE2](https://www.rancher.com/) has been one of the best to work with. It is intuitive, easy to use, and has a great community. It's the distribution we run our production clusters on. If security and performance are important to you, RKE2 is a decent option. RKE2 is a CNCF-certified Kubernetes distribution that is secure by default and has a small footprint. It will set up a conformant cluster you can start using in minutes. More importantly, it is easy to maintain and upgrade. While the Rancher server is lightweight, it is important to run it on a separate server to avoid conflicts and issues during setup and later on. ## Install Rancher The first thing we will do is set up the Rancher server. This server will be used to manage your Kubernetes clusters. **1. Initial setup** Go to the [Latitude.sh console](https://metal.new) and **create one server with Ubuntu 24.04**. A server with 16GB of RAM is enough. **2. Install k3s on the Rancher server** SSH into the server and run the following command. ```bash theme={null} curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="v1.28.11-rc1+k3s2" sh -s - server --cluster-init ``` > [!NOTE] > > Version 1.28 is the latest supported version as of this writing. **3. Setup kubectl on your local machine** Copy the contents of `/etc/rancher/k3s/k3s.yaml`. ```bash theme={null} sudo cat /etc/rancher/k3s/k3s.yaml ``` On your local machine, create a new file (e.g., `rke2-kubeconfig.yaml`) and paste the contents of the `k3s.yaml` file into it. Update the server URL in the kubeconfig file to point to the Rancher server's IP address. Leave the IP URL with HTTPs and port 6443. ```yaml theme={null} apiVersion: v1 clusters: - cluster: certificate-authority-data: ... server: https://:6443 name: default ... # trimmed for brevity ``` Open the terminal and set the `KUBECONFIG` environment variable to point to the location of your kubeconfig file: ```bash theme={null} export KUBECONFIG=/path/to/rke2-kubeconfig.yaml ``` > [!TIP] > > Add to your shell profile file (e.g., \~/.bashrc or \~/.zshrc) to make it > persistent across terminal sessions. Verify that you can access the Rancher server by running `kubectl get nodes`. It should display the node of your Rancher cluster, similar to the following: ```bash theme={null} $ kubectl get nodes NAME STATUS ROLES AGE VERSION kubernetes-on-bare-metal Ready control-plane,etcd,master 17m v1.28.11-rc1+k3s2 ``` **4. Install Rancher with Helm** To proceed, you will need to have [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) and [helm](https://helm.sh/docs/intro/install/) installed on your local machine. From your local terminal, run the following commands. ```bash Unix theme={null} helm repo add rancher-latest https://releases.rancher.com/server-charts/latest kubectl create namespace cattle-system kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.crds.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm install cert-manager jetstack/cert-manager \ --namespace cert-manager \ --create-namespace ``` ```powershell Powershell theme={null} helm repo add rancher-latest https://releases.rancher.com/server-charts/latest kubectl create namespace cattle-system kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.crds.yaml helm repo add jetstack https://charts.jetstack.io helm repo update helm install cert-manager jetstack/cert-manager ` --namespace cert-manager ` --create-namespace ``` > [!NOTE] > > cert-manager v1.15.1 is the latest version as of this writing. Go to > [https://github.com/cert-manager/cert-manager/releases](https://github.com/cert-manager/cert-manager/releases) to find the latest > version. We are now ready to install Rancher. Rancher requires a domain name to forward traffic to the Rancher server. For the sake of simplicity, we will use sslip.io, a fake domain name that doesn't require any setup. ```bash Unix theme={null} helm install rancher rancher-latest/rancher \ --namespace cattle-system \ --set hostname=.sslip.io \ --set replicas=1 \ --set bootstrapPassword= ``` ```powershell Powershell theme={null} helm install rancher rancher-latest/rancher ` --namespace cattle-system ` --set hostname=.sslip.io ` --set replicas=1 ` --set bootstrapPassword= ``` Go to `https://.sslip.io` and log in with the password you have set for the Rancher admin user. You should see the following screen: ![Rancher console](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/rke2/rancher-console.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=0fba6c4c10a917103a47e8ef9cfb7e78) > [!WARNING] > > Rancher takes a few minutes to initialize. Don't worry if you see a 404 error when you access the domain. Just wait a little longer. ## Create the K8s cluster Choose your adventure 👇 **Install manually** **1. Create 3 servers** [Create three more servers](https://metal.new) in the same location of the Rancher server. **2. Create the cluster** From the Rancher UI, click on Create then select the Custom option. Set a name for your cluster and click Create. You don't need to change any of the other settings. You can always come back and change them later. On the cluster registration page, leave `etcd`, `Control Plane`, and `Worker` checked. Click on **Show Advanced**, select one of the servers you created for the cluster, and add its hostname and public IP. **Bonus:** If you want cluster communication through a private network, set up a [private network](/docs/networking/private-networks) and add the private IP under Node Private IP. In Step 3, as we are using a self-signed certificate, check the Insecure option. If you set up your domain with TLS, leave insecure unchecked. Copy the registration command and run it on the first server, the same server you used to install Rancher. You should see it being registered. Repeat the same process for the other two servers. You can run different roles on different servers. For example, you can run `etcd` and `Control Plane` on one server and `Worker` on the other two. **3. That's it** It takes a few minutes for nodes to join the cluster. When the process is complete, your cluster's state will be *Active*. From there you can download the kubeconfig file and use it to access the cluster. ![Active Rancher RKE2 cluster on Latitude.sh](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/rke2/active-cluster.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=472fa9894e2364ff8aab574347bb910c) Go to your new cluster on the sidebar and start using it. ![RKE2 Cluster view](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/rke2/k8s-on-lsh-cluster.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=8e1d938be6d68904c48435c44b9069b1) **Terraform plan** > **[Read the guide and get the code](/docs/guides/terraform-rancher)** > > Complete Terraform guide for automated deployment > **[Just get the code](https://github.com/latitudesh/examples/tree/main/terraform/kubernetes-rancher)** > > Direct access to the Terraform configuration files # Setting up persistent storage for Kubernetes with Longhorn Source: https://www.latitude.sh/docs/guides/kubernetes-persistent-storage-longhorn Configure storage to retain application data on your K8s cluster [Longhorn](https://longhorn.io/docs/1.7.2/what-is-longhorn/) is a free, open-source distributed block storage system for Kubernetes that keeps things lightweight while handling replication and persistence for your workloads.​​​​​​​​​​​​​​​​ If you've got a K8s cluster deployed on Latitude.sh and need reliable container storage, this guide will get you there. ## Prerequisites * A [Kubernetes cluster](/docs/guides/kubernetes-on-bare-metal) with at least 3 nodes * [kubectl CLI](https://kubernetes.io/docs/tasks/tools/) installed on your local workstation * [Helm](https://helm.sh/docs/intro/install/) installed (for installing Longhorn) ## Step 1: Prepare your cluster **1. Check available disks** Run `lsblk` on each node to find available disks and partitions to dedicate to Longhorn. **2. Label nodes (Optional)** Label your nodes to control which ones will be used for Longhorn storage: ```shell theme={null} kubectl label nodes longhorn=true ``` ## Step 2: Install Longhorn Longhorn can be installed on a K8s cluster in [several ways](https://longhorn.io/docs/1.7.2/deploy/install/). In this guide, we'll go with [Helm](https://longhorn.io/docs/1.7.2/deploy/install/install-with-helm/). **1. Add Longhorn repository** Add the Longhorn Helm repository: ```shell theme={null} helm repo add longhorn https://charts.longhorn.io helm repo update ``` **2. Install Longhorn** Run this command to install Longhorn: ```shell theme={null} helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace ``` **3. Verify installation** Verify the installation: ```shell theme={null} kubectl -n longhorn-system get pod ``` All pods should be running without errors. ## Step 3: Access the Longhorn UI **1. Check services** Run this command to check if the Longhorn services are up: ```shell theme={null} kubectl -n longhorn-system get svc ``` The output should be something like this: ![Longhorn frontend service](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/longhorn-frontend-ip.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=cb8dad123a59d867633fd6dab2a9524f) **2. Set up port forwarding** Set up port forwarding to the frontend service: ```shell theme={null} kubectl port-forward services/longhorn-frontend 8080:http -n longhorn-system ``` **3. Access dashboard** Navigate to `http://localhost:8080` in your browser to access the Longhorn UI. You'll be taken to this dashboard: ![Longhorn dashboard UI](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/longhorn-ui.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=6130d8af630e0952b06f31ecf892c739) ## Step 4: Configure storage **1. Check nodes** In the Longhorn UI, navigate to **Node** and check if your disks are detected automatically. ![Longhorn node page](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/longhorn-node-page.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=017846af23a15e98c715db958c32f45a) **2. Define disk usage limits** Define disk usage limits and scheduling. Make sure your nodes have enough space to handle the intended workload. ## Step 5: Create a StorageClass **1. Create StorageClass manifest** Create a StorageClass manifest named `longhorn-storageclass.yaml`: ```yaml theme={null} apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: longhorn provisioner: driver.longhorn.io allowVolumeExpansion: true reclaimPolicy: Delete volumeBindingMode: Immediate ``` **2. Apply StorageClass** Apply the StorageClass: ```shell theme={null} kubectl apply -f longhorn-storageclass.yaml ``` **3. Set as default (Optional)** Set the StorageClass as default: ```shell theme={null} kubectl patch storageclass longhorn -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}' ``` ## Step 6: Create a PersistentVolumeClaim (PVC) **1. Create PVC manifest** Create a PersistentVolumeClaim YAML file named `longhorn-pvc.yaml`: ```yaml theme={null} apiVersion: v1 kind: PersistentVolumeClaim metadata: name: longhorn-pvc spec: accessModes: - ReadWriteOnce storageClassName: longhorn resources: requests: storage: 5Gi ``` **2. Apply PVC** Apply the PVC: ```shell theme={null} kubectl apply -f longhorn-pvc.yaml ``` **3. Verify PVC** Verify the PVC: ```shell theme={null} kubectl get pvc ``` Make sure the status shows **Bound** to confirm it worked. ## Step 7: Use the PVC in a Pod **1. Create Pod manifest** Create a Pod that Uses the PVC, save this as `longhorn-pod.yaml`: ```yaml theme={null} apiVersion: v1 kind: Pod metadata: name: longhorn-test-pod spec: containers: - name: longhorn-test image: nginx volumeMounts: - mountPath: "/usr/share/nginx/html" name: longhorn-storage volumes: - name: longhorn-storage persistentVolumeClaim: claimName: longhorn-pvc ``` **2. Deploy Pod** Deploy the Pod: ```shell theme={null} kubectl apply -f longhorn-pod.yaml ``` **3. Check Pod status** Check Pod status: ```shell theme={null} kubectl get pods ``` The Pod should be running without issues. You can check if the data persists by inspecting the mounted directory. ## Troubleshooting * If Longhorn nodes show as unschedulable, check disk space and ensure no taints are blocking pods. * For performance tuning, you can adjust the number of replicas for each volume in the Longhorn UI under **Settings > Default Settings**. * If using firewalls, ensure ports 9500-9600 are open for communication between Longhorn components. ## That's it! You've got Longhorn running and ready to handle your persistent storage needs. # CLASTIX Source: https://www.latitude.sh/docs/guides/managed-k8s-clastix Setting up managed bare metal nodes in a Kubernetes cluster In this guide, you'll learn how to configure bare metal servers as Kubernetes worker nodes using the CLASTIX platform. This setup combines the ease of Managed K8s with the control and performance of dedicated hardware. Let's get started! You can also use Terraform to set up your K8s cluster. Check our setup guide [here](https://github.com/latitudesh/examples/tree/main/terraform/kubernetes-clastix). ## Requirements * 2 or more [Latitude.sh](https://www.latitude.sh/) servers * [Kubectl](https://kubernetes.io/docs/tasks/tools/) installed on your local workstation ## Step 1: Set up your Kubernetes control plane **1. Access CLASTIX playground** Access the [CLASTIX playground](https://console.clastix.cloud/) and log in with your GitHub account. ![CLASTIX sign in](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-sign-in.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=6d4ac9cb3369c3d75ac542896c816586) **2. Create your first cluster** Click **Create your first cluster**. ![Create first CLASTIX cluster](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-create-1st-cluster.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=c2347570b65dc097bf7fa092e0f0e77d) **3. Configure cluster settings** Give the cluster a name and choose the Kubernetes version. ![CLASTIX cluster name](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-cluster-name.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=ae8d337265f3b1c10f902c88255999a7) **4. Select cluster components** Select the components CoreDNS, Konnectivity, and kube-proxy, then click **Create**: ![CLASTIX cluster components](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-cluster-components.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=f28de400e2029482a04e11b984d39d1f) **5. Wait for cluster to be ready** Wait a few seconds until the status of your Kubernetes Control Plane appears "Ready." ![CLASTIX cluster status](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-cluster-status.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=69041feb25a5b99d7285cffd7bdc637e) ## Step 2: Add the bare metal worker nodes **1. Deploy servers** Go to your [Latitude.sh console](https://metal.new/) and deploy two or more servers with **Ubuntu 22.04** or **24.04**. **2. Access your servers** In the server list, click the key icon on the right side of the server row, copy the **login snippet**, and paste it into your terminal to log in. For more details, see [our docs](https://www.latitude.sh/docs/servers/deploying-a-server). ![CLASTIX server credentials](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-server-credentials.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=3fafd239d46dbd41b41bd1ab9cbc56fd) **3. Install dependencies** After logging in, run the following command to update the package list and install socat and conntrack: ```shell theme={null} sudo apt update && sudo apt install -y socat conntrack ``` Repeat this process for each server. **4. Join nodes to cluster** From the CLASTIX console, click on your cluster's badge to open details, copy the **Yaki join command** provided, and paste it into your terminal to add the server as a worker node. ![CLASTIX join command](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-join-command.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=b7b472822712feede1fdc7c36d84f682) After your machines join the Kubernetes cluster, they will appear in the "List of nodes." ![CLASTIX nodes list](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-nodes-list.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=5b56a1bd919a80a79743126b8b379227) ## Step 3: Set up kubeconfig **1. Download kubeconfig** From the CLASTIX console, copy the kubeconfig and save it in a `file clastix-kubeconfig.yaml` on your workstation. **2. Configure kubectl** Set the KUBECONFIG environment variable to point to the location of the kubeconfig file: ```shell theme={null} export KUBECONFIG=/path/to/clastix-kubeconfig.yaml ``` ## Step 4: Install networking add-ons Your worker nodes will appear "Not Ready" until networking is configured. Follow these steps to install a [CNI plugin](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/), such as [Calico](https://github.com/clastix/calico-cni). **1. Add Calico CNI plugin** From the CLASTIX console, add a new add-on for Calico by filling in the necessary fields. ![CLASTIX CNI plugin](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-cni-plugin.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=803259176c9a99c82197971c20b0859b) The new add-on is now listed: ![CLASTIX Calico](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-calico.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=25042a1c6b093ea9668f2b5c1e2b3fdb) **2. Wait for nodes to be ready** Wait a few moments until your nodes transition to "Ready". ![CLASTIX nodes ready](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/clastix-nodes-ready.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=8387fc8dcd9ac09376922e9d5a7da3b8) ## All set! Your Kubernetes cluster is now up and running with bare metal nodes, ready for scaling. To optimize traffic management across your nodes, check out our guide on [Kubernetes load balancing](/docs/guides/kubernetes-load-balancing-on-bare-metal). # Nomad and Consul Source: https://www.latitude.sh/docs/guides/nomad-consul-terraform Deploy a Nomad cluster with Consul service mesh using Terraform on bare metal [Nomad](https://www.nomadproject.io/) is a cluster manager and scheduler that can be used to deploy and manage containers and non-containerized applications across a fleet of servers. It is a great tool to deploy applications on Latitude.sh as it requires less resources than Kubernetes and is easier to use. [Consul](https://www.consul.io/) is a service mesh that can be used to provide service discovery and networking to Nomad. It is a great tool to deploy on Latitude.sh as it provides a simple way to connect applications together and to the outside world. If you are not familiar with Terraform, read [Using Terraform with Latitude.sh](/docs/guides/terraform) first. ## Prerequisites * A Latitude.sh account. [Sign up](https://www.latitude.sh/dashboard/signup) * Terraform CLI installed. [Install Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) * A Latitude.sh API key. [Authentication](https://www.latitude.sh/docs/api-reference/authentication) * A Latitude.sh project with an SSH key. [Add an SSH key](https://www.latitude.sh/docs/ssh#adding-your-ssh-key) This guide will help you deploy a Nomad cluster with Consul for networking on Latitude.sh. It creates a Nomad cluster with 1 server and 1 client, sets up a private network between the nodes, and creates a Consul cluster on the same servers. The Nomad and Consul clusters will be connected. This guide uses Ubuntu 24.04 LTS. Not all commands are guaranteed to work on other operating systems. **1. Download the contents of the repository** The [terraform-nomad-consul](https://github.com/latitudesh/examples/tree/main/terraform/nomad-consul) directory on the `latitude.sh/examples` repository is the easiest way to get started. This directory contains all files required to deploy and set up the cluster. After creating the files to your local working directory, open the terminal and export your Latitude.sh API key to an environment variable and initialize Terraform. ```bash theme={null} export LATITUDESH_AUTH_TOKEN= terraform init ``` **2. Set up variables** The `variables.tf` file contains all variables that are used in the Terraform configuration. You will change the values of these variables to customize your deployment, replacing the default values with your own. Variables that you will need to change: * `project_id`: Go to the dashboard, select the project you want to deploy the cluster on, and click on Project settings. Copy the ID from the top-right corner of the page. * `operating_system`: The operating system of choice to deploy your servers and clients. The default value is `ubuntu_24_04_x64_lts`. The setup scripts are not guaranteed to work on other operating systems and might require modification. * `plan`: The slug of the plan you want to use. The slug is exactly like the plan name, but uses hyphens instead of dots. To use the c3.small.x86 plan, add `c3-small-x86` as the plan variable value. * `nomad_server_count` and `nomad_client_count`: The number of Nomad servers and clients you want to deploy. The default values are 1 for both. For production environments, it is recommended to use at least 3 servers and 3 clients. * `nomad_region`: The Latitude.sh location your cluster will be deployed to. The value is the location's slug. Get the slug from the [List all regions](https://www.latitude.sh/docs/api-reference/get-regions) API endpoint. * Make sure the plan and location are available in the region you selected. You can easily test this by going to the server create page in the dashboard * `nomad_vlan_id`: Go to the Latitude.sh dashboard. Click on *Private networks* in the sidebar. Create a VLAN on the location your cluster will be deployed to. The variable value is the *VID*. * `ssh_key_id`: Go to the Latitude.sh dashboard, click on Project settings and SSH Keys. Copy the ID of the SSH key you want to use. * `private_key_path`: The path to the private key file on your local machine. This is the private key that matches the public key you added to the project. You only need to change this if the path to the private key is different from `~/.ssh/id_rsa`. * Make sure ssh key is not passphrase protected otherwise Terraform won't be able to connect to it to install the dependencies. Save the file. **3. Plan and apply your changes** When all variables are set up, go back to the Terminal and run ```bash theme={null} terraform plan ``` Review the changes and, if all looks good, run ```bash theme={null} terraform apply ``` Wait for all servers to be deployed. Terraform will let you know when the process finishes. **4. Access your cluster** Copy the public IP of one of your Nomad Servers and add `:4646`. For example, if one of your Nomad servers' public IP is 189.1.2.3, you will access the Nomad UI at `http://189.1.2.3:4646`. **5. Deploying a job** To see the Nomad cluster in action, create and execute a job. You can do this programmatically, but this guide won't cover that. Instead, use the Nomad UI to deploy your job. This example uses a simple Docker image to have each client node echo "Hello, world!" via an HTTP server. Open the Nomad interface and go to the Jobs page. Click on *Run Job*. You will write the job definition in HCL, HashiCorp's configuration language. For this example, use the job script provided below: ```hcl theme={null} job "hello-world-job" { datacenters = ["dc-DAL-1"] # Replace DAL with the actual region slug where your cluster is deployed. type = "service" group "docker-example" { count = 1 task "docker-server" { driver = "docker" config { image = "hashicorp/http-echo:latest" args = [ "-listen", ":3030", "-text", "Hello, world!", ] } resources { network { mbits = 10 port "http" { static = "3030" } } } } } } ``` ## Adding new servers and clients You can add new servers and clients to your cluster by increasing the number of nodes in [variables.tf](https://github.com/latitudesh/examples/blob/main/terraform/nomad-consul/variables.tf) under `nomad_server_count` and `nomad_client_count`. * If you are adding a new server, you must go to `/etc/consul.d/consul.hcl` on all the existing servers in the cluster and add the private IP of the new server. * You can also join servers by using the command `nomad server join `. You can read more about this command at [https://developer.hashicorp.com/nomad/docs/commands/server/join](https://developer.hashicorp.com/nomad/docs/commands/server/join). ## Further reading * HashiCorp Nomad Tutorials: [https://developer.hashicorp.com/nomad/tutorials](https://developer.hashicorp.com/nomad/tutorials) * Add authentication with SSO: [https://developer.hashicorp.com/nomad/tutorials/single-sign-on](https://developer.hashicorp.com/nomad/tutorials/single-sign-on) ## Troubleshooting ### Servers or clients not showing up in the Nomad UI You should see the number of Client and Server nodes you provisioned by accessing the cluster. If you do not see the correct number of either servers or clients, it's probably because the private networking is not working correctly. **Check that the private network is working** If you didn't change the script, your servers should have the following private IPs configured: * Nomad servers: Starts at 10.8.0.1, where the last octet is the server number. So, for `nomad-server-1` the IP would be 10.8.0.1, for `nomad-server-2` the IP is 10.8.0.2, and so on. * Nomad clients: Starts at 10.8.0.10, where the last octet is the client number plus 9. So, for `nomad-client-1` the IP would be 10.8.0.10, for `nomad-client-2` the IP is 10.8.0.11, and so on. Go to one of the servers in your cluster and ping the private IP of another. For example, if `nomad-client-1` isn't showing up on your cluster, log in to `nomad-server-1` and ping 10.8.0.10. The server should be pinging. Otherwise, the private network isn't working. Review your settings and reach out to us if you still have issues. **Check netplan and consul settings** * Go to `/etc/netplan/50-cloud-init.yaml` and check if the settings look correct. Read [Private networking](/docs/networking/private-networks) if you're unfamiliar with how Netplan should be set up. # Set up a private cloud on bare metal with Harvester Source: https://www.latitude.sh/docs/guides/private-cloud-harvester Learn how to build a scalable private cloud on Latitude.sh from setup to deployment Building a private cloud on bare metal gives you both flexibility and control. It provides cloud-like agility with the dedicated performance of physical servers. This keeps you in charge of your infrastructure, avoiding the limitations of public cloud providers. In this guide, we'll walk you through setting up your own private cloud on the [Latitude.sh platform](https://www.latitude.sh/dashboard) using [Harvester](https://harvesterhci.io/), an open-source hyper-converged infrastructure (HCI) solution. Harvester simplifies managing virtual machines and [Kubernetes clusters](/docs/guides/kubernetes-on-bare-metal) on your servers, giving you a unified system that supports cloud-native workloads from the core to the edge. So let's jump right in! ## Requirements * 1 [Latitude.sh](https://www.latitude.sh/) server (3 recommended for high availability, but not required) * [Harvester iPXE script](https://github.com/latitudesh/examples/blob/main/custom-images-v2/harvester/boot.ipxe) for cluster setup * IP address range to assign to your VMs (at least 1 /29 block for both cluster and VM, or 2 /29 blocks to separate traffic between them) ## Step 1: Prepare the iPXE script **1. Get the iPXE script** Go to [the Latitude.sh repository](https://github.com/latitudesh/examples/blob/main/custom-images-v2/harvester/boot.ipxe), or copy the script below to automatically install Harvester on your server: ```shell theme={null} #!ipxe dhcp kernel https://releases.rancher.com/harvester/master/harvester-master-vmlinuz-amd64 ip=dhcp net.ifnames=1 \ root=live:https://releases.rancher.com/harvester/master/harvester-master-rootfs-amd64.squashfs \ console=tty1 console=ttyS1,115200n8 \ harvester.install.skipchecks=true \ harvester.install.tty=tty1 initrd https://releases.rancher.com/harvester/master/harvester-master-initrd-amd64 boot ``` > [!WARNING] > > In the `boot.ipxe` script, you must replace `HARVESTER-CONFIG-FILE` with the URL of your customized Harvester configuration file. **2. Configure the Harvester config file** For the first node, configure the HARVESTER-CONFIG-FILE.yaml shown below, replacing the placeholders with your environment details. ```yaml theme={null} scheme_version: 1 token: {{CLUSTER-TOKEN}} os: hostname: {{HOSTNAME}} # Set a hostname. This can be omitted if DHCP server offers hostnames. ssh_authorized_keys: - {{SSH_PUBLIC_KEY}} password: {{ENCRYPTED_PASSWORD}} ntp_servers: - 0.suse.pool.ntp.org - 1.suse.pool.ntp.org dns_nameservers: - 8.8.8.8 - 1.1.1.1 install: mode: create management_interface: interfaces: - name: {{INTERFACE_NAME}} default_route: true method: static bond_options: miimon: 100 ip: {{PUBLIC_IP}} subnet_mask: {{PUBLIC_SUBNET}} gateway: {{PUBLIC_GW}} device: {{BLOCK-STORAGE-DEVICE}} iso_url: https://releases.rancher.com/harvester/master/harvester-master-amd64.iso tty: ttyS1,115200n8 # For machines without a VGA console vip: {{VIRTUAL-IP-FOR-CLUSTER-MANAGEMENT}} vip_mode: static # Or static vip_hw_addr: # Leave empty when vip_mode is static ``` To replace the placeholders in the HARVESTER-CONFIG-FILE.yaml, follow these steps: 1. **CLUSTER-TOKEN**: This is a unique token used to create the cluster and join new nodes. You can generate a random string (e.g., openssl rand -hex 16) or create a meaningful token. 2. **HOSTNAME**: Replace this with the hostname of your server. This can be anything meaningful to you, like node1, harvester-master, etc. 3. **SSH\_PUBLIC\_KEY**: Enter your public SSH key here. This allows you to log in to the server via SSH after installation. You can find your public key by running `cat ~/.ssh/id_rsa.pub` on your local machine. 4. **ENCRYPTED\_PASSWORD**: Replace this with an encrypted password (hashed with bcrypt, for example). You can generate this using a password generator or encryption tool like [openssl](https://github.com/openssl/openssl). 5. **INTERFACE\_NAME**: Set this to your network interface name (e.g., eth0, enp1s0, etc.). You can find this by running `ip a` or `ifconfig` on your server to identify the network interface name. 6. **PUBLIC\_IP**: This should be the static public IP address assigned to the server. It's the IP you want to use for the management interface. 7. **PUBLIC\_SUBNET**: Replace this with the subnet mask of the network your server is in. 8. **PUBLIC\_GW**: This is the gateway IP address for your network, typically the IP address of your router. 9. **BLOCK-STORAGE-DEVICE**: Specify the storage device where Harvester should be installed. This is typically something like `/dev/sda` or `/dev/nvme0n1`, depending on your server's disk layout. 10. **VIRTUAL-IP-FOR-CLUSTER-MANAGEMENT**: This is the virtual IP (VIP) that will be used for cluster management. It must be an unused IP in the same subnet as your public IP and dedicated for cluster management. ## Step 2: Request additional IPs Depending on the number of VMs and services you plan to deploy, calculate the required IP addresses. If you're running out of available IPs, you may need to request additional IPs. **1. Submit IP request** Go to **Networking > IP Addresses** on the [Latitude.sh dashboard](https://www.latitude.sh/dashboard) to request additional IPs: * Select the required number of IPs. **Request at least 1 /29 block for both cluster and VM, or 2 /29 blocks to separate traffic between them.** * Provide a justification for the request (e.g., setting up a Harvester-based private cloud) **2. Assign IPs to Virtual Machines** Once you've received additional IP addresses, assign them to your VMs in Harvester. ## Step 3: Boot the server In the [Latitude.sh dashboard](https://www.latitude.sh/dashboard), click **Reinstall** from the server Actions menu, choose **Custom image (iPXE)** as the OS, and paste your modified **boot.ipxe script** with the URL of your customized Harvester configuration file. This will automatically install Harvester on the server and configure it as the management node for your cluster. ![Harvester iPXE installation](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/harvester-ipxe.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=d4ae8c110b7e68b3e1f7742ccb779625) For additional nodes, boot each node using the corresponding iPXE script and the HARVESTER-ADD-NODE-TO-CLUSTER.yaml configuration to join the existing cluster. ## All set! With your Harvester cluster deployed, you now have full control over your cloud-native workloads and the flexibility to scale as your needs evolve. This setup ensures high-performance virtualization while maintaining the manageability of cloud environments. # Using Terraform with Latitude.sh Source: https://www.latitude.sh/docs/guides/terraform Use infrastructure as code with Terraform on Latitude.sh for consistent, repeatable deployments [Terraform](https://www.terraform.io/) is an infrastructure as code (IaC) driven software that allows you to programmatically configure your project infrastructure using configuration files and version control. Terraform ensures logical management and monitoring of resources such as servers, networks, and cloud storage instead of a manual operation for each required resource. These infrastructure configurations are handled via a declarative language called HCL (HashiCorp Configuration Language). For example, when you create a project or deploy a server, Terraform parses your code and translates it to an API call to the resource provider. Terraform integrations are called Providers. Providers are published to the [Terraform Registry](https://registry.terraform.io/) and can be consumed to quickly integrate infrastructure providers with the resources that compose your infrastructure. This guide will teach you how to use the [Latitude.sh Terraform provider](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs). Latitude.sh is a [verified HashiCorp partner](https://www.hashicorp.com/partners/tech/latitude-sh). ## About the integration With the [Latitude.sh Terraform provider](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs) you can: * Create and update projects * Create and update servers * Create and update SSH keys * Use [data sources](https://developer.hashicorp.com/terraform/language/data-sources) and [outputs](https://developer.hashicorp.com/terraform/language/values/outputs) to retrieve data. If you already use Terraform to manage your infrastructure, getting started with the Latitude.sh provider is straightforward. If you don't use Terraform yet, it shouldn't take more than 10 minutes to get familiar with the basic concepts and start versioning your infrastructure. ## Getting started **1. Install Terraform CLI** Install the Terraform CLI. [This guide](https://developer.hashicorp.com/terraform/downloads) explains how to do this for your operating system. **2. Create API token** Create a Latitude.sh API token. [Here](https://www.latitude.sh/docs/api-reference/authentication) is how to create an API token. **3. Export API token** Export the API token as a variable ```sh theme={null} export LATITUDESH_AUTH_TOKEN=your_api_token ``` ## Example integration We will start by creating a project, getting the `id` of the project we just created, then adding our ssh key to that project, and finally creating a server that deploys to our new project and uses the SSH key we just added. **1. Create project directory** Create a directory for your Terraform project. ```bash theme={null} mkdir latitudesh-terraform-example cd latitudesh-terraform-example ``` **2. Create main.tf** Create a file named `main.tf` with the following content: ```hcl theme={null} terraform { required_providers { latitudesh = { source = "latitudesh/latitudesh" version = "~> 0.1.5" # Make sure you are using the latest version published to the Terraform registry } } } ``` **3. Initialize project** Run the following command in your terminal to Initialize the project. ```bash theme={null} terraform init ``` You should see a success message after initializing the project that will contain something like this: > Terraform has been successfully initialized! > > You may now begin working with Terraform. Try running "terraform plan" to see\ > any changes that are required for your infrastructure. All Terraform commands\ > should now work. > > If you ever set or change modules or backend configuration for Terraform,\ > rerun this command to reinitialize your working directory. If you forget, other\ > commands will detect it and remind you to do so if necessary. **4. Create configuration files** Now we are finally ready to start creating infrastructure with Terraform. While you can add your codified resources to `main.tf`, as your infrastructure grows, it gets hard and dangerous to manage things from a single file, so it is usually best to split your files from the beginning. Create a file named `variables.tf` with the following content. This is optional but useful for this guide. ```hcl variables.tf theme={null} # Determines the server configuration we are going to deploy variable "plan" { description = "Latitude.sh server plan" default = "c2-small-x86" } # Determines the location we are going to deploy to variable "region" { description = "Latitude.sh server region slug" default = "MH1" } variable "ssh_public_key" { description = "Latitude.sh SSH public key" } ``` Create the following files ```hcl outputs.tf theme={null} # Prints the IPv4 of the server we just created when the deploy is finished on the terminal output "server-ip" { value = latitudesh_server.server.primary_ip_v4 } ``` ```hcl project.tf theme={null} # Creates our project resource "latitudesh_project" "project" { name = "Terraform example project" description = "Latitude.sh Terraform Integration" environment = "Development" # Development, Production or Staging } ``` ```hcl server.tf theme={null} resource "latitudesh_server" "server" { hostname = "terraform-guide.latitude.sh" operating_system = "ubuntu_22_04_x64_lts" plan = var.plan # Uses the plan slug we defined on variables.tf project = latitudesh_project.project.id # Uses the project id we will create site = var.region # Uses the region slug we defined on variables.tf billing = "monthly" # hourly, monthly (default) or yearly. See the billing note below ssh_keys = [latitudesh_ssh_key.ssh_key.id] # Uses the ssh id we will create. If you don't have an SSH key ready to use, you can remove this line and servers will be created with password auth instead } ``` > [!NOTE] > > `billing` accepts `hourly` and `monthly` for on-demand projects, and `yearly` for reserved projects. If you omit it, the server defaults to `monthly`, charged upfront based on the proration of the current billing cycle. On recent provider versions, `terraform plan` shows the resolved default (`billing = "monthly"`) on create rather than `(known after apply)`, so you can confirm how a new server will be billed before you apply. Use `hourly` for dynamic or short-lived workloads to avoid a full monthly charge. See [On demand vs. Reserved](/docs/billing/on-demand-vs-reserved) for how each billing type is priced. Optional if you have an SSH key in hand. If not, remove the `ssh_keys` from `server.tf` and the ssh section from `variables.tf` and ignore the next file. ```hcl ssh_key.tf theme={null} resource "latitudesh_ssh_key" "ssh_key" { project = latitudesh_project.project.id # Uses the project id we will create name = "John's Key" # Name your key so it's easy to identify later public_key = var.ssh_public_key } ``` ## Run the plan Now that we have all our files organized and referenced, we can create the infrastructure defined in them. Let's start by reviewing the changes that will be made. **1. Review the plan** Run this on your terminal: ```bash theme={null} terraform plan ``` If you decide to use an SSH key, Terraform will ask for your public SSH key. Terraform will list every action it will take after we apply our plan. Review to make sure everything is how you want it to be. **2. Apply the plan** Apply the plan: ```bash theme={null} terraform apply ``` Paste your public SSH key again when requested and type *yes* on the prompt. ## That's it You've just created three different resources with relationships between them. Commit this code to your repository to start versioning your infrastructure like a pro! Cleaning up is easy, just run the destroy command to rollback: ```shell theme={null} terraform apply -destroy ``` We touched the surface of what you can do with the Latitude.sh Terraform provider. To learn more, review the following links: * [Latitude.sh Terraform provider docs](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs) * [Contribute to the provider with code, feature requests, or bug reports](https://github.com/latitudesh/terraform-provider-latitudesh) # CLASTIX Source: https://www.latitude.sh/docs/guides/terraform-clastix Deploy Kubernetes worker nodes to CLASTIX managed clusters using Terraform ## Prerequisites * [Terraform](https://www.terraform.io/downloads.html) installed * [NPM](https://www.npmjs.com/get-npm) installed * A [Clastix Cloud](https://console.clastix.cloud) Tenant Control Plane with a join token command string * A [Latitude.sh](https://www.latitude.sh) account with an API key ## Important notes * Ensure you have correctly provisioned a Tenant Control Plane on [Clastix Cloud Console](https://console.clastix.cloud) as this Terraform plan does not create it. Make sure you have the join token command string from the console. * The default configuration creates 3 worker nodes to join the Tenant Control Plane and form your baremetal Kubernetes cluster. Adjust the `node_count` variable if you need a different number of nodes. **1. Download the example files** Download the example files using degit: ```bash theme={null} npx degit latitudesh/examples/terraform/kubernetes-clastix my-kubernetes-cluster cd my-kubernetes-cluster ``` **2. Initialize Terraform** `bash terraform init ` **3. Update variables** Update the `variables.tf` file with your specific details: * `JOIN_URL`: The URL of Tenant Control Plane to join. Find this on the [Clastix Cloud Console](https://console.clastix.cloud). * `JOIN_TOKEN`: The token to join the Tenant Control Plane. Find this on the [Clastix Cloud Console](https://console.clastix.cloud). You will be asked for it when planning and applying your plan. * `JOIN_TOKEN_CACERT_HASH`: The CA certificate hash of the token. Find this on the [Clastix Cloud Console](https://console.clastix.cloud). You will be asked for it when planning and applying your plan. * `LATITUDESH_AUTH_TOKEN`: Don't hardcode this. You will be asked for it when planning and applying your plan. * `project_id`: The ID of the project you want to deploy to. Find this from the [home page](https://www.latitude.sh/dashboard) in the console. * `plan`: The plan slug. For example, for the m4.metal.medium, use `m4-metal-medium` * `region`: The slug of the location you want to deploy to. E.g., for Dallas use `DAL`. Find all with the api.latitude.sh/locations endpoint. * `ssh_key_id`: The ID of the SSH key you want to use for the nodes. Find this in the console under Project settings > SSH keys * `private_key_path`: This script will access your servers during setup. Add the local path in your computer where the private key of the SSH Key inserted above. * `server_count`: Optional. Number of nodes to provision and add to the cluster. **4. Review configuration** (Optional) Modify other variables in `variables.tf` as needed: * `project_id`: Your Latitude project ID * `region`: The region where you want to deploy the cluster * `plan`: The server plan for the nodes * `node_count`: The number of worker nodes (default is 3) Review and adjust the `main.tf` file if necessary. **5. Plan your Terraform execution** `bash terraform plan ` **6. Apply the changes** If the plan looks good, apply the changes: ```bash theme={null} terraform apply ``` Confirm by typing `yes` when prompted. ## Cleaning up To destroy the resources created by this Terraform plan: ```bash theme={null} terraform destroy ``` ## Support If you encounter any issues or have questions, please open an issue in the [examples repository](https://github.com/latitudesh/examples/issues). # Terraform Cloud best practices Source: https://www.latitude.sh/docs/guides/terraform-cloud Collaborate on infrastructure as code with team workflows and security guardrails When working with multiple people, managing your infrastructure with Terraform becomes challenging. When that happens, adding visibility and guardrails to your Terraform plans becomes important. [Terraform Cloud](https://app.terraform.io) is a great option for collaborating with other developers. Some of its most useful features are the ability to run plans remotely, shared state files, and add security features to avoid human error messing up your Latitude.sh infrastructure. This is an opinionated setup for Latitude.sh on Terraform Cloud based on best practices we created when using Terraform with Latitude.sh ourselves. ## Set up After signing up for Terraform Cloud, set up your workspace. We recommend using a Git repository. We use *GitHub*, but Terraform Cloud also allows *GitLab*, *Bitbucket* and *Azure DevOps* to be connected. Create one directory on your git repo and one workspace in Terraform Cloud for each of your Latitude.sh projects. So, if like us, you have a *Development* and a \_Production \_ project on your Latitude.sh account that you want to manage with Terraform, this is what the root of your repo should look like. ![Latitude.sh projects are represented by one directory each.](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-cloud/537b364-github-repository.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=89b5cd87615cc6cf69e06bceabab35bc) Now go back to the workspace setup in Terraform Cloud. In the Configure settings section, click on **Advanced options**. In the **Terraform Working Directory** input, type the directory name you set up previously. ![Terraform Cloud workspace setup advanced options](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-cloud/de488e1-advanced-options.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=c8e0307a6570bc28b1a33df547bef279) In the **Apply method** select, choose **Auto Apply** for environments you don't care about breaking, such as *development*, and **Manual apply** for critical environments, like *production*. We strongly recommend leaving **Automatic speculative plans** selected. This is a good setup to allow your team to move quickly when developing while keeping critical environments less error-prone. Here's what your workspace should look like now ![Terraform Cloud workspaces](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-cloud/55ff6b5-terraform-cloud-workspaces.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=b1c9d48874def0b3f687c2f53df627ce) ## Variables Select a workspace and go to **Variables**. Add a new sensitive variable named `LATITUDESH_AUTH_TOKEN` with your Latitude.sh [API Key](https://www.latitude.sh/docs/api-reference/get-api-keys) as value. ![Terraform Cloud workspace variables](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-cloud/dd7195f-workspace-variables.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=55226d90b46582902bd9fb8222a858c7) Do this for all workspaces and create one API key for each. ## Additional recommendations With this setup, whenever you push changes to the `main` branch * Terraform Cloud will plan and apply your plan for the *development* workspace. * Terraform Cloud will plan and wait for confirmation to apply your plan for the *production* workspace. You have to go to Terraform Cloud's dashboard and approve the changes. Because Terraform has the potential for highly destructive actions like reimaging an instance or completely destroying it, it's important to harden your git repo. Here's what we recommend: 1. Restrict repository access to developers working on your infrastructure. 2. Create **branch protection rules**, the most important being protecting your `main` branch. # Import your infrastructure into Terraform Source: https://www.latitude.sh/docs/guides/terraform-import Import existing resources into Terraform to manage them with infrastructure as code New to Terraform? [Start here](/docs/guides/terraform) *** The Latitude.sh Terraform provider supports importing existing infrastructure into Terraform. This feature is useful when you want to add existing Latitude.sh resources to Terraform to start managing them with code. Before importing your resources, it helps to understand how Terraform keeps track of your infrastructure. Terraform maps the attributes and metadata of your resources to its internal state and save it to a local file named `terraform.tfstate`. Every change to a `.tf` file will be compared with the Terraform state to determine what changes need to be made. Here is an example of a `.tfstate` file: ```json theme={null} { "version": 4, "terraform_version": "1.8.2", "serial": 20, "lineage": "", "outputs": {}, "resources": [ { "mode": "managed", "type": "latitudesh_project", "name": "guide_project", "provider": "provider[\"registry.terraform.io/latitudesh/latitudesh\"]", "instances": [ { "schema_version": 0, "attributes": { "created": "2024-05-08T22:16:58+00:00", "description": "Terraform Guides example project", "environment": "Development", "id": "proj_7pWRawmOpNrD6", "name": "Terraform Guide", "tags": [], "updated": "2024-05-09T15:20:57+00:00" }, "sensitive_attributes": [], "private": "" } ] } ], "check_results": null } ``` Editing the state file directly is discouraged. Terraform modifies it to reflect your current infrastructure by running `terraform refresh` before `terraform plan`. > [!NOTE] > > If you need more advanced state management, use the `terraform state` command > to edit it in a more controlled environment. ## Migrating your existing Infrastructure If you already have resources deployed on Latitude.sh, importing them on Terraform is straightforward. Let's walk through an example: ### Creating the `.tf` file To start the migration of our infrastructure, let's initialize a Terraform project in a new directory: ```bash theme={null} # create a new directory mkdir latitudesh-infra && cd latitudesh-infra # create the main file touch main.tf ``` In our main file, we need to set the provider and its version: ```bash theme={null} # main.tf terraform { required_providers { latitudesh = { source = "latitudesh/latitudesh" version = "1.1.0" # check the latest version at https://registry.terraform.io/providers/latitudesh/latitudesh/latest } } } ``` Now we can initialize terraform to download the Latitude.sh provider and start managing our infrastructure: ```bash theme={null} terraform init ``` Before we start importing our infrastructure, we need to export our Auth Token so Terraform can communicate with the Latitude.sh API and access our resources: ```bash theme={null} export LATITUDESH_AUTH_TOKEN= # replace with your actual token ``` Now that we are all set up, let's import our resources ### Importing resources Let's exemplify the import process with a **Project** resource. To begin we'll need an `import` block with two attributes * to: The resource defined inside Terraform that will be used to manage your infrastructure. * id: The id of the existing resource. > [!NOTE] > > You can find the id of the project in the **Home** section of the dashboard. Now let's create the file for importing this project: ```bash theme={null} # projects.tf import { to = latitudesh_project.guide_project id = "proj_7pWRawmOpNrD6" # replace with the project id you want to import } resource "latitudesh_project" "guide_project" { name = "Terraform Import Guide" environment = "Development" } ``` You'll notice that we have set both the name and the environment of the Project resource. This is needed because both are required attributes. Running `terraform plan` should render something like this: ```bash theme={null} latitudesh_project.guide_project: Preparing import... [id=proj_7pWRawmOpNrD6] latitudesh_project.guide_project: Refreshing state... [id=proj_7pWRawmOpNrD6] Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: ~ update in-place Terraform will perform the following actions: # latitudesh_project.guide_project will be updated in-place # (imported from "proj_7pWRawmOpNrD6") ~ resource "latitudesh_project" "guide_project" { created = "2024-05-08T22:16:58+00:00" - description = "Terraform Guides example project" -> null environment = "Development" id = "proj_7pWRawmOpNrD6" name = "Terraform Guide" tags = [] updated = "2024-06-04T22:20:09+00:00" } Plan: 1 to import, 0 to add, 1 to change, 0 to destroy. ``` Here you'll notice that there's a "-" signal before the description. That occurs because we haven't defined a description attribute in our project resource block. to avoid updating the resource we will add the missing attribute to our resource. ```bash theme={null} # projects.tf import { to = latitudesh_project.guide_project id = "proj_7pWRawmOpNrD6" } resource "latitudesh_project" "guide_project" { name = "Terraform Import Guide" description = "Terraform Guides example project" environment = "Development" } ``` Run `terraform plan` again. If everything looks good, run `terraform apply` to import the resource: ```bash theme={null} latitudesh_project.guide_project: Preparing import... [id=proj_7pWRawmOpNrD6] latitudesh_project.guide_project: Refreshing state... [id=proj_7pWRawmOpNrD6] Terraform will perform the following actions: # latitudesh_project.guide_project will be imported resource "latitudesh_project" "guide_project" { created = "2024-05-08T22:16:58+00:00" description = "Terraform Guides example project" environment = "Development" id = "proj_7pWRawmOpNrD6" name = "Terraform Import Guide" tags = [] updated = "2024-06-04T22:20:09+00:00" } Plan: 1 to import, 0 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: ``` And it's done! You can now manage this resource with Terraform. Now let's import some other resources. All Latitude.sh resources and how to define them can be found on the [Latitude.sh Terraform Provider docs](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs). ### Finding resources IDs As we've seen, it is necessary to pass the ID of the resource to the import block. The fastest way to obtain the IDs is by using our CLI, but you can also find them from the dashboard and API. To learn how to set up the CLI, see the [Latitude.sh CLI documentation page](https://www.latitude.sh/docs/cli). After installation, you can use the `lsh` command in your terminal to access your infrastructure. For example, to find the IDs of your tags, run `lsh tags list`. ![Tags list from the Latitude.sh CLI](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-import/tags-table.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=37b175ccddc7ac807f7571b318f37ad0) ### Importing using for\_each Here we have two servers that we want to import using Terraform's for\_each syntax: ![Latitude.sh server list](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/guides/terraform-import/servers-2.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=dbc79240ae4063292a9868e6cee774b1) Create the following file: ```bash theme={null} # servers.tf locals { servers = { "tf-server" = { id = "sv_6B9VaLJmZN7vr", # replace with the server id you want to import project = latitudesh_project.guide_project.id operating_system = "ubuntu_22_04_x64_lts" site = "SAO" plan = "c2-small-x86" tags = [ "tag_mQ1EM1yJ6XIYlO1DKxXpIdevjPP" ] # replace with the tag id you want to import }, "another-server" = { id = "sv_7pWRawQkENrD6" # replace with the server id you want to import project = latitudesh_project.guide_project.id operating_system = "ubuntu_22_04_x64_lts" site = "SAO" plan = "c2-small-x86" tags = [] }, } } import { for_each = local.servers id = each.value.id to = latitudesh_server.server[each.key] } resource "latitudesh_server" "server" { for_each = local.servers hostname = each.key project = each.value.project operating_system = each.value.operating_system site = each.value.site plan = each.value.plan } ``` Here we defined the server attributes as a local value object. Then we used the `for_each` keyword to loop over the objects and get their key-value pair to build our resource. Running `terraform apply` should import the servers successfully. > [!NOTE] > > Always run `terraform plan` before applying your changes to verify the changes > that will be made. ### Generating Configuration Terraform allows us to generate the resource based on our import block. Let's import the rest of our infrastructure. ```bash theme={null} # import.tf import { to = latitudesh_virtual_network.vlan id = "proj_7pWRawmOpNrD6:vlan_dexA0qj36NlQV" } import { to = latitudesh_vlan_assignment.vlan_assignment id = "proj_7pWRawmOpNrD6:vnasg_Yx2za1g9KNVrL" } import { to = latitudesh_ssh_key.sshkey id = "proj_7pWRawmOpNrD6:ssh_MDEOaPmyq0wgB" } import { to = latitudesh_user_data.user_data id = "proj_7pWRawmOpNrD6:ud_owPOapbdNB4xr" } import { to = latitudesh_tag.guide_tag id = "proj_7pWRawmOpNrD6:tag_mQ1EM1yJ6XIYlO1DKxXpIdevjPP" } ``` The IDs here are in the form of `projectID:resourceID`. This is needed for nested resources. On the [provider documentation](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs), you can verify if a resource is a nested resource or not. To automatically generate the resource blocks, run: ```bash theme={null} terraform plan -generate-config-out=generated_resources.tf ``` This will create a `generated_resources.tf` file with the resource blocks of the remaining infrastructure. Generating configuration is still an experimental feature, and it's highly encouraged for you to verify the generated resources. You can edit and organize resources in different files. When you've finished verifying the generated resources, run `terraform apply` to finish your configuration. Now you know everything needed to import your existing Latitude.sh infrastructure to Terraform. Happy coding! # Rancher RKE2 Source: https://www.latitude.sh/docs/guides/terraform-rancher Deploy Kubernetes clusters using Rancher and Terraform on bare metal servers ## Prerequisites * [Terraform](https://www.terraform.io/downloads.html) installed * [NPM](https://www.npmjs.com/get-npm) installed * An existing Rancher server. [Create it](/docs/guides/kubernetes-on-bare-metal) if you don't have one. * A Latitude.sh account with an API key ## Important notes * Ensure you have an existing Rancher server where the cluster will be created. This Terraform plan does not create the Rancher server. * The `rancher_api_url` should be in the format `https:///v3`. * Make sure your Rancher server is accessible from the internet, as the Latitude.sh servers will need to communicate with it. * The default configuration creates a cluster with 3 worker nodes. Adjust the `node_count` variable if you need a different number of nodes. **1. Download the example files** Download the example files using degit: ```bash theme={null} npx degit latitudesh/examples/terraform/kubernetes-rancher my-kubernetes-cluster cd my-kubernetes-cluster ``` **2. Initialize Terraform** `bash terraform init ` **3. Update variables** Update the `variables.tf` file with your details: * `LATITUDESH_AUTH_TOKEN`: Don't hardcode this. You will be asked for it when planning and applying your plan. * `project_id`: The ID of the project you want to deploy to. Find this from the [home page](https://www.latitude.sh/dashboard) in the console by clicking on the three dots above the project followed by *Copy ID*. * `plan`: The plan slug. Simply replace the plan name with hyphens instead of dots. For example, for the m4.metal.medium, use `m4-metal-medium` * `region`: The slug of the location you want to deploy to. E.g., for Dallas use `DAL`. Find all with the api.latitude.sh/locations endpoint. * `ssh_key_id`: The ID of the SSH key you want to use for the nodes. Find this in the console under Project settings > SSH keys * `private_key_path`: This script will access your servers during setup. Add the local path in your computer where the private key of the SSH Key inserted above. * `rancher_api_url`: The `rancher_api_url` should be in the format `https:///v3`. * `RANCHER_ACCESS_KEY`: The access key is available in your control plane. Find more details on the [Rancher docs](https://ranchermanager.docs.rancher.com/reference-guides/user-settings/api-keys). Create one from the Rancher UI by going to *User > Account & API Keys*. * `RANCHER_SECRET_KEY`: The token's password. Find more details on [Rancher Doc](https://ranchermanager.docs.rancher.com/reference-guides/user-settings/api-keys) in the API Keys. * `server_count`: Number of nodes to provision and add to the cluster. **4. Plan your Terraform execution** `bash terraform plan -var-file="secret.tfvars" ` **5. Apply the changes** If the plan looks good, apply the changes: ```bash theme={null} terraform apply -var-file="secret.tfvars" ``` Confirm by typing `yes` when prompted. ## Cleaning Up To destroy the resources created by this Terraform plan: ```bash theme={null} terraform destroy ``` ## Support If you encounter any issues or have questions, please open an issue in the [examples repository](https://github.com/latitudesh/examples/issues). # Latitude.sh documentation Source: https://www.latitude.sh/docs/index Deploy and manage bare metal servers, virtual machines, storage, and networking on Latitude.sh Latitude.sh enables you to deploy and manage bare metal servers and virtual machines globally, with the flexibility of the cloud and the performance, security, and control of dedicated infrastructure. This documentation is a deep dive into the platform and all of its features, with everything you need to know to run your workloads on Latitude.sh from the [dashboard](/docs/dashboard/overview), the [API](/docs/api-reference/summary), the [CLI](/docs/cli), and the [SDKs](/docs/client-libraries). [Get started ](/docs/account-setup/sign-up) ## Quick start Four steps from a new account to a running server. > **[Sign up](/docs/account-setup/sign-up)** > > Create your account with your company email or SSO. > **[Verify your account](/docs/account-setup/verify-account)** > > Add a payment method and verify your identity to unlock deployments. > **[Create a project](/docs/projects)** > > Projects group your servers and network resources. > **[Deploy a server](/docs/servers/deploying-a-server)** > > Pick a plan, a location, and an operating system, then deploy. ## Products ### Compute Run your workloads on dedicated hardware, bare or virtualized. > **[Bare metal](/docs/servers/deploying-a-server)** > > Dedicated single-tenant servers, including Metal GPU plans, with full hardware control. > **[Virtual machines](/docs/vms/virtual-machines)** > > General-purpose VMs with backups, restore, and monitoring. Managed Kubernetes on Latitude.sh bare metal. ### Storage Persistent storage and data services that outlive your servers. > **[Object storage](/docs/storage/object-storage)** > > S3-compatible buckets that work with the tools you already use. Persistent volumes that attach to bare metal servers and outlive them. > **[File storage](/docs/storage/filesystem)** > > Shared, persistent filesystems for bare metal servers. > **[Managed Postgres](/docs/managed-databases)** > > Fully managed PostgreSQL with backups, monitoring, and trusted sources. ### Network How your infrastructure connects and stays protected. > **[Private networks](/docs/networking/private-networks)** > > Layer 2 networks between servers and VMs in the same location. Routed IP blocks that belong to a project and are shared by bonded servers. > **[IP addresses](/docs/networking/ips)** > > Management, Additional, Elastic, and BYOIP addresses, and how they differ. > **[Elastic IPs](/docs/networking/elastic-ips)** > > Portable IPv4 addresses you move between servers or announce over BGP. > **[BYOIP](/docs/networking/byoip)** > > Bring your own IPv4 prefixes to Latitude.sh infrastructure. > **[Firewall](/docs/networking/firewall)** > > Resource-level rules for servers and VMs, managed from one place. > **[DDoS protection](/docs/networking/ddos-protection)** > > Mitigation built and operated by Latitude.sh, included with all servers. ### Interconnection Private connectivity beyond a single location. > **[Cloud Gateway](/docs/networking/cloud-gateway)** > > Private, direct connections to major cloud providers. > **[Global Gateway](/docs/interconnection/global-gateway)** > > Private high-speed links between Latitude.sh locations. ## Platform How to organize your account and manage the platform day to day. > **[Dashboard](/docs/dashboard/overview)** > > Get to know the dashboard's topbar, home page, and sidebar. > **[Regions & locations](/docs/regions-locations)** > > Where Latitude.sh operates, and how regions and locations differ. > **[Projects](/docs/projects)** > > Organize your servers and network resources. Each project is invoiced separately. > **[Team management](/docs/teams/members)** > > Invite team members and manage their roles. > **[Account security](/docs/account-security/mfa)** > > Protect your account with MFA, SAML SSO, and passkeys. > **[Usage & billing](/docs/billing/overview)** > > Payment methods, invoices, on demand vs. reserved, and resource limits. ## Developer resources Automate and integrate Latitude.sh into your own tooling. > **[API reference](/docs/api-reference/summary)** > > JSON:API endpoints for every resource on the platform. > **[CLI](/docs/cli)** > > `lsh`, the open source command line interface. > **[SDKs](/docs/client-libraries)** > > Official TypeScript, Go, and Python SDKs. > **[Terraform](/docs/guides/terraform)** > > Manage your infrastructure as code with the Terraform provider. > **[MCP server](/docs/development/model-context-protocol)** > > Let AI agents manage your infrastructure through the hosted MCP server. > **[Postman Collection](/docs/development/postman)** > > Test and explore the API endpoints directly from Postman. > **[Examples](/docs/examples)** > > Ready-to-run examples for custom images, user data, storage, and Terraform. Browse all [developer resources](/docs/development). ## Guides Step-by-step tutorials for running production workloads on Latitude.sh. > **[Nomad and Consul](/docs/guides/nomad-consul-terraform)** > > Deploy a Nomad cluster with a Consul service mesh using Terraform. > **[Using Terraform with Latitude.sh](/docs/guides/terraform)** > > Use infrastructure as code for consistent, repeatable deployments. > **[Deploy a custom OS via IPMI](/docs/guides/ipmi-custom-os-deployment)** > > Install an operating system we don't offer using IPMI. > **[Set up a private cloud with Harvester](/docs/guides/private-cloud-harvester)** > > Build a scalable private cloud on Latitude.sh. Browse all [guides](/docs/guides). ## Updates & service status Follow what changed and check that everything is running. > **[Product changelog](https://www.latitude.sh/changelog)** > > Keep up to date with changes to the platform and products. > **[Status page](https://status.latitude.sh/)** > > Status of Latitude.sh services and scheduled maintenances. > **[Looking Glass](https://lg.latitude.sh/)** > > Test network performance with Latitude.sh's Looking Glass. ## Get help Talk to us about your account, your services, or your plans. > **[Contact support](/docs/support/contact-support)** > > Get help from the Latitude.sh AI agent or open a support ticket. > **[Contact sales](https://www.latitude.sh/contact)** > > Contact the sales team to discuss your needs. # Global Gateway Source: https://www.latitude.sh/docs/interconnection/global-gateway Private connections between Latitude.sh locations Global Gateway provides private, high-speed connections between Latitude.sh locations worldwide. Transfer data between your servers across different regions privately with enterprise-grade reliability. ## Benefits * **Private network connections**: Direct, secure connections between datacenters * **No additional costs**: No additional costs for data transfer between locations * **Low latency routing**: Optimized paths for faster data transfer * **Enterprise reliability**: Built on redundant, carrier-grade infrastructure ## How it works Global Gateway routes traffic between your servers' Latitude.sh-assigned public IPs through our private backbone instead of the public internet. This is enabled by default for all customers, so servers in different regions can communicate securely over this backbone without any additional setup. > [!NOTE] > > The default Global Gateway applies to traffic between **Latitude.sh-assigned public IPs** only. It does not extend [private networks (VLANs)](/docs/networking/private-networks) across regions. Private networks operate within a single location. If you need private network (VLAN) connectivity across multiple locations, you can request a [dedicated Global Gateway connection](#requesting-dedicated-connections). ## Default vs. dedicated connections | Feature | Default Global Gateway | Dedicated Global Gateway | | - | - | - | | Scope | Public IPs assigned by Latitude.sh | Private networks (VLANs) across regions | | Setup | Enabled automatically | Requested through the dashboard | | Configuration | No setup required | Custom bandwidth and routing | | Use case | General cross-region traffic over public IPs | Private L2/L3 connectivity between locations | ## Active connections View active Global Gateway connections in the [Global Gateway dashboard](https://www.latitude.sh/dashboard/interconnection/global-gateway). The dashboard shows bandwidth, latency, and network paths for all interconnections between Latitude.sh regions. Default connections are active for all customers and update automatically as new interconnections become available. ## Getting started Simply deploy servers in connected regions and traffic between their Latitude.sh-assigned public IPs will automatically route through the Global Gateway backbone. No additional configuration is required. To view active interconnections and monitor performance, visit the [Global Gateway dashboard](https://www.latitude.sh/dashboard/interconnection/global-gateway). ![Global Gateway dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/32.Docs25Q4.GlobalGateway.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=0d4e4294e3e887852cb750148671786a) ## Requesting dedicated connections For cross-region private network (VLAN) connectivity, or for higher bandwidth requirements, you can request dedicated Global Gateway connections through the dashboard: 1. Log in to the [dashboard](https://www.latitude.sh/dashboard) and select a project 2. Navigate to **Interconnection > Global Gateway** in the sidebar 3. Click **Request dedicated connection** 4. Select your origin and destination regions 5. Choose your required bandwidth (1 Gbps to 100 Gbps available) 6. Describe your use case and submit the request The team will review your request and configure the dedicated connection. ## Use cases * **Multi-region applications**: Deploy distributed applications across regions without egress costs * **Data replication**: Sync databases and storage between locations * **Disaster recovery**: Maintain backup systems in different regions * **Load balancing**: Distribute traffic across multiple datacenters * **Hybrid cloud**: Connect cloud resources to bare metal infrastructure * **Cross-region private networks**: Connect private VLANs across locations using a dedicated connection ## Billing Default Global Gateway usage is included at no additional cost. Data transfer between connected regions through Global Gateway does not incur egress charges. Dedicated connections may have additional charges, contact [support](https://www.latitude.sh/dashboard/support) for pricing details. # LKS Source: https://www.latitude.sh/docs/lks Managed Kubernetes on Latitude.sh bare metal Latitude Kubernetes Service (LKS) is managed Kubernetes on bare metal. Latitude.sh runs the Control Plane; you run your Workloads on Node Pools. You get a conformant, upstream Kubernetes Cluster and a kubeconfig, then manage your applications with standard Kubernetes tooling. > [!NOTE] > > LKS is in preview. Features and defaults may change. During the preview, LKS is managed from the dashboard; API, CLI, and SDK support is coming. ## What Latitude.sh manages * **Control Plane.** The API server and etcd run as a managed, highly available Control Plane. You don't size, access, or patch it. * **Networking.** Cilium is the Cluster CNI, configured and maintained for you. The Pod, Service, and Node IP ranges have defaults you can override when you create a Cluster. See [Cluster networking](/docs/lks/clusters#cluster-networking). * **LoadBalancer IPs.** A `Service` of type `LoadBalancer` is assigned a Latitude Elastic IP announced over BGP. See [Exposing Workloads](/docs/lks/exposing-workloads). * **Node images.** Node operating system images are provided by Latitude.sh and roll out through Node Pool upgrades. ## What you manage * **Workloads.** Your applications, their manifests, and their lifecycle. * **Node Pools.** The plan, size, Labels, and Taints of each Node Pool. See [Node Pools](/docs/lks/node-pools). * **Ingress and gateways.** LKS load balancing is L4. Bring your own Ingress or Gateway controller for HTTP routing. * **Observability, backups, and upgrades.** You run your monitoring stack, back up your data, and choose when to upgrade Kubernetes versions. ## Getting started Follow [Getting started](/docs/lks/getting-started) to create a Cluster, connect with `kubectl`, and run your first Workload. ## Shared responsibility For the full breakdown of what Latitude.sh operates and what you operate across the Cluster lifecycle, see [Shared responsibility](/docs/lks/shared-responsibility). # Clusters Source: https://www.latitude.sh/docs/lks/clusters Create, access, upgrade, and delete LKS Clusters from the dashboard An LKS Cluster is a managed Kubernetes Control Plane plus one or more [Node Pools](/docs/lks/node-pools) of bare metal Nodes. Latitude.sh runs the Control Plane; you manage the Cluster's Workloads and Node Pools. ## Prerequisites * A [verified account](/docs/account-setup/verify-account) with a [payment method](/docs/billing/payment-methods). * A [project](/docs/projects) selected in the dashboard. * [`kubectl`](https://kubernetes.io/docs/tasks/tools/#kubectl) installed on your machine. ## Create a Cluster **1. Open Cluster creation** Go to **LKS** in the sidebar and click **Create Cluster**. **2. Select a location** Choose the region where the Cluster runs. Plan availability and pricing vary by region. **3. Name the Cluster** Enter a name of 3-63 lowercase letters, numbers, or hyphens, starting and ending with a letter or number. It must be unique within the project. **4. Describe the Cluster (optional)** Add an optional description, up to 200 characters, to record what the Cluster is for. **5. Choose a Kubernetes version** Select the Kubernetes version for the Control Plane. The newest available version is selected by default. **6. Add Node Pools** Add one or more Node Pools. Each Node Pool has a **Mode**: **On-demand** provisions a number of **Nodes** from a **Plan**, and **Allocated** uses Servers you already have. Each Node Pool can carry its own Labels and Taints. See [Node Pools](/docs/lks/node-pools) for details. **7. Configure networking (optional)** Expand **Cluster networking** to set custom Pod, Service, and Node CIDRs. Most Clusters use the defaults. See [Cluster networking](#cluster-networking). **8. Create** Review the [hourly price](https://www.latitude.sh/pricing) and click **Create Cluster**. You're taken to the Cluster overview while it provisions. > [!NOTE] > > The Control Plane is fully managed. You don't size or access Control Plane Nodes, and no SSH keys are needed to create a Cluster. ## Cluster networking A Cluster has three IP ranges: the Pod CIDRs, the Service CIDRs, and the Node CIDRs. LKS applies defaults that fit most Clusters, so you can accept them and skip this. To set your own ranges, expand **Cluster networking** in the create form and enter one IPv4 CIDR per field. | Network | Default | Used for | | - | - | - | | Pod CIDRs | `10.0.0.0/12` | IP addresses assigned to Pods. | | Service CIDRs | `10.96.0.0/15` | Virtual IPs assigned to ClusterIP Services. | | Node CIDRs | `10.16.0.0/21` | Node addresses, from one range shared by every Node Pool. | > [!NOTE] > > Each field is a list (`pod_cidrs`, `service_cidrs`, `node_cidrs`) in the [create cluster API](/docs/api-reference/lks/create-an-lks-cluster), but only a single value per field is supported today. > > Only IPv4 ranges are accepted, and each must be a network address (host bits set to 0), for example `10.0.0.0/12`. > [!WARNING] > > The three ranges are set only when the Cluster is created and can't be changed afterward, and they must not overlap each other. Choose them with room to grow. ### How Pod addresses are allocated Cilium runs the Cluster network with cluster-pool IPAM. It carves the Pod CIDRs into a `/23` block for each Node, giving every Node about 510 Pod addresses, enough for the maximum of 500 Pods per Node. This per-Node block is fixed when the Cluster is created and is the same across every Node Pool. Because Cilium manages Pod IPAM, LKS does not use the Kubernetes `Node.spec.podCIDRs` field. Ignore it: it isn't populated and isn't the source of truth for a Node's Pod range. That range is recorded on the Node's `CiliumNode` resource instead. ### Sizing custom ranges Each Node takes a `/23` from the Pod CIDRs, so a shorter prefix allows more Nodes: | Pod CIDR prefix | Max Nodes | | - | - | | `/12` (default) | 2,048 | | `/14` | 512 | | `/16` | 128 | | `/18` | 32 | | `/20` | 8 | Size the Node CIDRs to hold at least as many addresses as the Pod CIDRs allow Nodes. A simple rule is to set the Node CIDR prefix to the Pod CIDR prefix plus 9: the default `/12` supports about 2,048 Nodes, matched by the default `/21` Node CIDRs. ## Cluster status The Cluster list and overview show the current state: | Status | Meaning | | - | - | | Provisioning | The Cluster is being created. | | Active | The Cluster is ready to use. | | Updating | A configuration change is being applied. | | Upgrading | A Kubernetes version upgrade is in progress. | | Degraded | The Cluster is running with reduced health. | | Paused | Paused by Latitude support; changes are blocked until it's unpaused. | | Deleting | The Cluster is being removed. | | Error | The last operation failed. | ## Access the Cluster Download the kubeconfig from the Cluster **Overview** tab, under **Cluster access**: * **Download kubeconfig**: save the file to your machine. * **Copy to clipboard**: copy the kubeconfig contents. * **View**: preview the kubeconfig in the dashboard. Connect with `kubectl`: ```bash theme={null} kubectl --kubeconfig=./my-cluster-kubeconfig.yaml get nodes ``` The kubeconfig is available once the Cluster is **Active**. ## Name and description On the **Settings** tab you can edit the Cluster's **Name** (its display name) and its **Description** (up to 200 characters). ## Upgrade the Kubernetes version Latitude.sh publishes the Kubernetes versions available for upgrade. To upgrade the Control Plane, open the **Settings** tab. When a newer version is available, the **Version** row shows **Upgrade to** `{version}`; otherwise it shows **Up to date**. > [!WARNING] > > A Control Plane upgrade can't be reversed. Node Pools stay on their current version until you upgrade them, and a Node Pool can run at most one minor version behind the Control Plane. Upgrade each pool after the Control Plane. See [Upgrade a Node Pool](/docs/lks/node-pools#upgrade-a-node-pool). ## Delete a Cluster Open the **Settings** tab and click **Delete**, or use **Delete Cluster** in the Cluster's actions menu. Type the Cluster name to confirm. > [!WARNING] > > Deleting a Cluster is permanent. All Node Pools and their Nodes are destroyed, the LoadBalancer IP is released, and all data and Workloads are lost. Servers in [allocated Node Pools](/docs/lks/node-pools#node-pool-modes) aren't destroyed. They're reinstalled with Ubuntu 24.04 and returned to your project. See [When a Server leaves an Allocated Node Pool](/docs/lks/node-pools#when-a-server-leaves-an-allocated-node-pool). # Exposing Workloads Source: https://www.latitude.sh/docs/lks/exposing-workloads How LKS exposes Services to the Internet with L4 load balancing over BGP LKS exposes Workloads to the Internet through Kubernetes `Service` objects of type `LoadBalancer`. Each LoadBalancer Service is backed by Latitude [Elastic IPs via BGP](/docs/networking/elastic-ips-bgp) and MetalLB: it's assigned an Elastic IP that is announced from your Cluster over BGP, so traffic to that address reaches your Nodes. ## How it works * **L4 load balancing.** LoadBalancer Services operate at layer 4 (TCP and UDP). There's no managed HTTP layer. * **Elastic IP over BGP.** When you create a LoadBalancer Service, an Elastic IP is allocated in the Cluster's region and MetalLB announces it over BGP, then updates the Service with the address. * **Bring your own ingress.** For HTTP routing, TLS termination, or path and host rules, run your own Ingress or Gateway controller (such as Traefik or a Gateway API implementation) behind a LoadBalancer Service. LKS doesn't install one. ## High availability For a Service to stay reachable when a Node is lost, run at least two replicas of its backend, spread across Nodes. Set `externalTrafficPolicy: Local` on the Service. Under this policy the IP is announced only from Nodes that run a backing Pod, which preserves the client source IP and routes traffic straight to a local Pod. With a single replica, the address is announced from just one Node, so the Service goes down if that Node or Pod fails. Two or more replicas across Nodes keep it announced from several Nodes. ## Configure a Service For the required Service fields and the supported annotations, see [LoadBalancer Services](/docs/lks/load-balancer-services). # Getting started Source: https://www.latitude.sh/docs/lks/getting-started Create an LKS Cluster, connect with kubectl, and deploy your first Workload This guide walks you through creating your first Cluster, connecting to it, and running a Workload. For the full reference on each step, see [Clusters](/docs/lks/clusters) and [Node Pools](/docs/lks/node-pools). ## Prerequisites * A [verified account](/docs/account-setup/verify-account) with a [payment method](/docs/billing/payment-methods). * A [project](/docs/projects) selected in the dashboard. * [`kubectl`](https://kubernetes.io/docs/tasks/tools/#kubectl) installed on your machine. **1. Create a Cluster** Open the [dashboard](/docs/dashboard/overview), select a project, and go to **LKS** in the sidebar. Click **Create Cluster** and set: * **Location**: the region where the Cluster runs. * **Cluster name**: 3-63 lowercase letters, numbers, or hyphens, starting and ending with a letter or number. * **Kubernetes version**: the newest available version is selected by default. * **Node Pools**: add at least one Node Pool, choose a **Plan**, and set the number of **Nodes**. Review the [hourly price](https://www.latitude.sh/pricing) and click **Create Cluster**. Provisioning takes a few minutes. See [Clusters](/docs/lks/clusters) and [Node Pools](/docs/lks/node-pools) for all options. **2. Connect with kubectl** Once the Cluster is **Active**, open its **Overview** tab. Under **Cluster access**, click **Download kubeconfig**. Point `kubectl` at the file and list your Nodes: ```bash theme={null} kubectl --kubeconfig=./my-cluster-kubeconfig.yaml get nodes ``` You should see your Nodes listed, all in the `Ready` state. **3. Deploy a Workload** Apply a small Deployment to confirm the Cluster runs your Workloads: ```bash theme={null} kubectl --kubeconfig=./my-cluster-kubeconfig.yaml create deployment hello \ --image=nginx --replicas=2 ``` Check that the Pods are running: ```bash theme={null} kubectl --kubeconfig=./my-cluster-kubeconfig.yaml get pods -l app=hello ``` ## Next steps * Expose your Workload to the Internet with a LoadBalancer Service. See [Exposing Workloads](/docs/lks/exposing-workloads). * Add, scale, or tune worker capacity. See [Node Pools](/docs/lks/node-pools). # LoadBalancer Services Source: https://www.latitude.sh/docs/lks/load-balancer-services Required fields and supported annotations for LKS LoadBalancer Services To expose a Workload, create a Kubernetes `Service` of type `LoadBalancer`. This page covers the one required field and the annotations LKS supports. For the model behind it, see [Exposing Workloads](/docs/lks/exposing-workloads). ## Required: the LoadBalancer class Every LKS LoadBalancer Service must set `spec.loadBalancerClass` to `latitude.sh/elastic-ip`. Without it, the Service never receives an external IP and its `EXTERNAL-IP` stays ``. ```yaml theme={null} apiVersion: v1 kind: Service metadata: name: web spec: type: LoadBalancer loadBalancerClass: latitude.sh/elastic-ip selector: app: web ports: - name: http port: 80 targetPort: 8080 ``` Apply it and read back the assigned address: ```bash theme={null} kubectl get service web ``` A Latitude [Elastic IP](/docs/networking/elastic-ips-bgp) is allocated in the Cluster's region and, once it's announced, populates `EXTERNAL-IP`. ## Preserve the client source IP To keep the Service highly available and preserve the client source IP, set `externalTrafficPolicy: Local` and run at least two replicas across Nodes. See [High availability](/docs/lks/exposing-workloads#high-availability). ```yaml theme={null} spec: type: LoadBalancer loadBalancerClass: latitude.sh/elastic-ip externalTrafficPolicy: Local # ... ``` ## Annotations LKS supports two annotations for controlling the Elastic IP behind a Service. | Annotation | Value | Default | Effect | | - | - | - | - | | `lks.latitude.sh/adopt-elastic-ip` | Elastic IP id | None. A new Elastic IP is allocated. | Reuse an existing Latitude Elastic IP instead of allocating a new one. Keeps a stable address across Service recreation. | | `lks.latitude.sh/preserve-elastic-ip` | `"true"` | `"false"` | Keep the Elastic IP reserved when the Service is deleted, so you can reuse it later. | ```yaml theme={null} apiVersion: v1 kind: Service metadata: name: web annotations: lks.latitude.sh/adopt-elastic-ip: '' lks.latitude.sh/preserve-elastic-ip: 'true' spec: type: LoadBalancer loadBalancerClass: latitude.sh/elastic-ip # ... ``` ### Adopting an Elastic IP The Elastic IP you adopt must belong to the same project and region as the Cluster and be a BGP-mode address that isn't already in use. If it doesn't qualify, the Service stays pending and the platform records the reason as an event on the Service: ```bash theme={null} kubectl describe service web ``` ### Preserving an Elastic IP > [!NOTE] > > A preserved Elastic IP stays reserved after you delete the Service, and reserved Elastic IPs [continue to bill](https://www.latitude.sh/pricing/networking#ips). Release it when you no longer need the address. # Node Pools Source: https://www.latitude.sh/docs/lks/node-pools Create, scale, label, taint, upgrade, and delete LKS Node Pools on new or existing Servers A Node Pool is a group of identical bare metal Nodes. Every Node in a Node Pool shares the same plan. A Cluster can have several Node Pools, letting you run different plans side by side (for example CPU and GPU Nodes) and target Workloads at specific Node Pools with Labels and Taints. ## Node Pool modes Every Node Pool has a mode. You set it when you create the Node Pool, and it can't be changed afterward. * **On-demand** (default): LKS provisions new Servers from a plan. * **Allocated**: LKS runs the Node Pool on bare metal Servers you already have in the Cluster's project. Each Server is reinstalled with the Node image and joins the Cluster. | | On-demand | Allocated | | - | - | - | | Nodes run on | New Servers provisioned from a plan. | Servers you already have in the Cluster's project. | | Size | A plan and a Node count. | The Servers you select, all on one plan. | | Change capacity | Scale the Node count. | Add or remove your Servers. | | Upgrades | A new Node joins before an old one is removed. | Each Server is reinstalled, one at a time. | | When a Node leaves | Its Server is destroyed. | Its Server is reinstalled with Ubuntu 24.04 and stays in your project. | | Billing | Hourly [bare metal pricing](https://www.latitude.sh/pricing) per Node. | The Server keeps its existing billing. | A Cluster can mix both modes. For example, an allocated Node Pool with Servers you already run and an on-demand Node Pool for extra capacity. > [!WARNING] > > Adding a Server to an allocated Node Pool reinstalls it. Everything on the Server is lost, so back up any data you need before you select it. ## Server requirements for Allocated mode A Server can join an allocated Node Pool when it: * Is a bare metal Server in the Cluster's project and location. * Was deployed as a [BGP-ready Server](/docs/networking/elastic-ips-bgp#deploy-a-bgp-ready-server). This is set when the Server is deployed and can't be turned on afterward. * Isn't bonded onto a [public network](/docs/networking/public-networks) and has no [Firewall](/docs/networking/firewall) assigned. * Isn't locked, scheduled for deletion, in [rescue mode](/docs/servers/rescue-mode), or still being deployed or reinstalled. * Isn't already in a Node Pool of any Cluster. All Servers in an allocated Node Pool must be on the same plan, and the Node Pool takes its plan from them. The Server picker lists only Servers that can join. Servers you can't pick right now, such as one already selected for another Node Pool in the same form, show the reason next to their name. ### Why a Server can't join When a Server can't join, the picker or the error message shows one of these reasons: | Reason | What to do | | - | - | | Not found in this project | Use a Server in the Cluster's project, or [move the Server](/docs/servers/change-project) to it first. | | In a different location | Use a Server in the Cluster's location. | | Not a bare metal server | Use a bare metal Server. | | Already in a Node Pool | Remove the Server from its current Node Pool first. | | Locked | Unlock the Server. | | Scheduled for deletion | [Cancel the scheduled deletion](/docs/servers/deleting-a-server#canceling-a-scheduled-deletion), or use another Server. | | In rescue mode | Take the Server out of [rescue mode](/docs/servers/rescue-mode). | | Being provisioned | Wait for the deploy or reinstall to finish. | | Assigned to a Firewall | [Remove the Firewall assignment](/docs/networking/firewall#assigning-a-firewall-to-resources). | | Attached to a public network | [Remove the Server from its public network](/docs/servers/network-bonding#removing-a-bond-teardown). | | Network setup not supported | The Server's network setup can't run LKS Nodes. Use another Server. | | Not deployed BGP-ready | Use a Server deployed as [BGP-ready](/docs/networking/elastic-ips-bgp#deploy-a-bgp-ready-server). An existing Server can't be made BGP-ready. | | Different plan from the selected servers | Select Servers of a single plan. | | Selected for another Node Pool | A Server can be in only one Node Pool. Clear it from the other Node Pool first. | ## Add a Node Pool **1. Open the Node Pools tab** Open your Cluster and go to the **Node Pools** tab. Click **Add Node Pool**. **2. Choose a mode** Under **Mode**, keep **On-demand** to provision new Servers, or select **Allocated** to use Servers you already have. See [Node Pool modes](#node-pool-modes). **3. Choose the Nodes** * **On-demand**: choose a **Plan** for every Node in the Node Pool, and how many **Nodes** to provision (at least 1). * **Allocated**: under **Servers**, select at least one Server. The list shows the project's Servers at the Cluster's location that meet the [Server requirements](#server-requirements-for-allocated-mode). **4. Configure the Node Pool** Set: * **Description** (optional): a short description of the Node Pool, up to 200 characters. * **Max Pods per Node** (optional): the maximum number of Pods that can run on each Node. See [Max Pods per Node](#max-pods-per-node). * **Labels** (optional): key-value pairs applied to every Node in the Node Pool. * **Taints** (optional): rules that repel Pods from the Node Pool's Nodes unless the Pods tolerate them. **5. Add the Node Pool** Click **Add Node Pool**. An on-demand Node Pool provisions its Nodes; an allocated Node Pool reinstalls its Servers with the Node image. The Nodes then join the Cluster. You can also add multiple Node Pools, in either mode, when you first [create a Cluster](/docs/lks/clusters#create-a-cluster). ## Max Pods per Node Max Pods per Node sets the maximum number of Pods that can run on each Node in a Node Pool. You set it with the **Max Pods per Node** field when you create the Node Pool. It's optional and can't be changed after the Node Pool is created. * Enter a whole number between **16 and 500**. * Leave it blank to use the default of **110**. The value is shown on the Node Pool's detail view; a Node Pool left at the default shows `110 (default)`. ## Node Pool status The Node Pools table shows each pool's current state. These are separate from the [Cluster status](/docs/lks/clusters#cluster-status). | Status | Meaning | | - | - | | Provisioning | The pool is being created and its Nodes are joining. | | Active | The pool is ready. | | Scaling | The pool's Node count is changing. | | Updating | A change to the pool's Labels or Taints is being applied. | | Upgrading | The pool's Kubernetes version is being upgraded. | | Degraded | The pool is running with reduced health. | | Paused | Paused by Latitude support; changes are blocked until it's unpaused. | | Deleting | The pool is being removed. | | Error | The last operation failed. | ## Scale an On-demand Node Pool Open the **Node Pools** tab, open the Node Pool's actions menu, and click **Scale**. Set the new Node count and confirm. Scaling up provisions and joins new Nodes; scaling down drains and removes Nodes. A Node Pool must always have at least one Node. You can't scale a Node Pool to 0 Nodes. To remove its capacity entirely, delete the Node Pool instead. > [!NOTE] > > When a Node is removed (scaling down, upgrading a Node Pool, or deleting a Node Pool), LKS drains it first and gives its Pods up to 30 minutes to reschedule elsewhere. If a Pod can't be evicted within that window, for example because of a misconfigured PodDisruptionBudget, the Node is removed once the 30 minutes elapse. ## Scale an Allocated Node Pool Allocated Node Pools scale by their Servers, not by a count. Open the **Node Pools** tab, open the Node Pool's actions menu, and click **Manage servers**. Select the Servers to add, clear the ones to remove, and click **Save changes**. The Node Pool shows **Scaling** while the changes are applied. * Added Servers are reinstalled with the Node image and join the Cluster. * Removed Servers are drained and returned to your project. See [When a Server leaves an Allocated Node Pool](#when-a-server-leaves-an-allocated-node-pool). An allocated Node Pool must keep at least one Server. To return all of them, delete the Node Pool. ## Rename a Node Pool You can rename a Node Pool after it's created. Open the Node Pool's actions menu and update its **Name**. This changes the display name only. ## Labels and Taints Labels and Taints steer Workloads to the right Nodes. * **Labels** are key-value pairs applied to every Node in the Node Pool. Use them as `nodeSelector` or affinity targets. See the Kubernetes guide to [Labels and Selectors](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/). * **Taints** repel Pods from the Node Pool's Nodes unless a Pod tolerates the Taint. Each Taint has a key, an optional value, and an effect: `NoSchedule`, `PreferNoSchedule`, or `NoExecute`. See the Kubernetes guide to [Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/). To change them on an existing Node Pool, open the Node Pool's actions menu and click **Edit Labels & Taints**. ### Rules * A Node Pool can have up to 50 Labels and up to 50 Taints. * Keys follow Kubernetes key syntax and may include an optional prefix (`prefix/name`). * A Taint effect must be `NoSchedule`, `PreferNoSchedule`, or `NoExecute`. The same key can appear with different effects, but not twice with the same effect. * These key prefixes are reserved and are rejected: `kubernetes.io`, `k8s.io`, `cluster.x-k8s.io`, and `lks.latitude.sh`, along with their subdomains. Keys without a prefix, such as `env` or `team`, are always allowed. > [!WARNING] > > The `NoExecute` effect evicts running Pods that don't tolerate the Taint from the Node Pool's Nodes. > [!WARNING] > > Keep at least one Node Pool, with at least one Node, free of `NoSchedule` and `NoExecute` Taints. LKS runs critical Pods such as the Cluster's DNS and load balancing on your Nodes. If every Node Pool carries a `NoSchedule` or `NoExecute` Taint, these Pods have nowhere to run and the Cluster can lose DNS and LoadBalancer functionality. ## Upgrade a Node Pool A Node Pool runs its own Kubernetes version and can trail the Control Plane by at most one minor version. After you upgrade the Control Plane, upgrade each Node Pool to match. Open the **Node Pools** tab. When a Node Pool is behind the Cluster version, its row shows **Upgrade available**. Open the Node Pool's actions menu and click **Upgrade version**. > [!WARNING] > > Upgrading a Node Pool recreates its Nodes and can't be reversed. Run your Workloads with enough replicas to tolerate Nodes being replaced. An allocated Node Pool gets no new Servers during an upgrade. LKS drains and reinstalls each Server in place, one at a time, so one Node at a time is out of service. A Node Pool with a single Server has no capacity while it upgrades; run at least two Servers to keep Workloads running. ## Node images and updates Node operating system images are provided and owned by Latitude.sh. New images reach your Nodes when you upgrade a Node Pool, scale it, or add a new Node Pool. There's no in-place OS patching for you to run. ## Delete a Node Pool Open the Node Pool's actions menu and click **Delete Node Pool**, then confirm. > [!WARNING] > > Deleting a Node Pool destroys its Nodes. Workloads running on them are rescheduled to other Node Pools when capacity is available, or stop if it isn't. Deleting an allocated Node Pool doesn't destroy its Servers. Each one is drained and returned to your project. See [When a Server leaves an Allocated Node Pool](#when-a-server-leaves-an-allocated-node-pool). ## Servers in Node Pools ### While a Server is a Node Every Node runs on a bare metal Server in the Cluster's project. LKS manages the Server while it's a Node, so these actions are blocked until it leaves its Node Pool: * Delete or schedule deletion. * Reinstall or rescue mode. * Power off. * Lock. * Change the hostname. * Move to another project. * Switch to yearly billing. You can still reboot the Server and edit its tags. In an allocated Node Pool, a Node that fails its health checks is repaired by reinstalling the same Server. ### Find the Server behind a Node On the **Node Pools** tab, expand a Node Pool's row or switch to **Nodes** to list the Nodes. Click a Node to open **Node details**, which shows its **Server**. Click **View server** to open the Server. ### When a Server leaves an Allocated Node Pool A Server leaves an allocated Node Pool when you remove it with **Manage servers**, delete its Node Pool, or delete the Cluster. In each case, LKS: 1. Drains the Node, giving its Pods up to 30 minutes to reschedule elsewhere. 2. Reinstalls the Server with Ubuntu 24.04, with no SSH keys or user data and a hostname based on its Server ID. 3. Returns the Server to your project. The Server keeps its billing. To use it again, [reinstall it](/docs/servers/reinstalling-a-server) with your own SSH keys and settings. # Shared responsibility Source: https://www.latitude.sh/docs/lks/shared-responsibility How responsibilities split between Latitude.sh and you across the LKS Cluster lifecycle Latitude.sh delivers and operates a managed Kubernetes Cluster: a highly available Control Plane, Node Pools of bare metal Nodes, core networking, and LoadBalancer IPs announced over BGP. Once you have your kubeconfig, day-2 operations (Workloads, upgrades, observability, backups) are yours. This page details what each side owns. ## At a glance > **Latitude.sh handles** > > The managed Control Plane, bare metal provisioning, Node images, Cilium networking, and LoadBalancer IP allocation and BGP announcement. > **You handle** > > Workloads, Node Pool configuration, Kubernetes version upgrades, ingress and gateways, storage, monitoring, backups, and network policies. ## RACI matrix The matrix uses standard RACI definitions: * **Responsible (R):** performs the work. * **Accountable (A):** owns the outcome. * **Consulted (C):** opinion is sought (two-way). * **Informed (I):** kept up to date (one-way). | Task / deliverable | Latitude.sh | Customer | Notes | | - | - | - | - | | Bare metal provisioning (rack, power, network) | A/R | I | Physical hardware health and connectivity. | | Managed Control Plane (API server, etcd) | A/R | I | Availability and health of the Control Plane. | | Control Plane version upgrades | R | A | You choose when to upgrade; Latitude.sh performs it. | | Core networking (Cilium CNI) | A/R | I | Opinionated, managed stack, not customer-replaceable. | | LoadBalancer IP allocation and BGP announcement | A/R | I | An Elastic IP per LoadBalancer Service, announced over BGP. | | Node images (operating system) | A/R | I | Provided by Latitude.sh; updated through Node Pool upgrades. | | Node Pool configuration (plan, size, Labels, Taints) | R | A/R | You define Node Pools; Latitude.sh provisions the Nodes. | | Node Pool scaling | R | A | You trigger scaling; Latitude.sh provisions or removes Nodes. | | Node Pool version upgrades | R | A/R | You trigger; Nodes are recreated on the new version. | | Workload deployment (Pods, Services) | I | A/R | All containerized applications. | | Ingress and gateways (L7) | I | A/R | Bring your own controller behind an L4 LoadBalancer Service. | | Persistent storage | I | A/R | Latitude CSI is coming soon. | | Monitoring and logging | I | A/R | Prometheus, Grafana, and similar stacks. | | Backup and disaster recovery | I | A/R | Workload and volume backups. | | Network policies and RBAC | I | A/R | In-cluster security posture. | | Kubeconfig delivery | A/R | I | Issued at provisioning, retrievable from the dashboard. | | Billing and metering | A/R | I | Hourly [bare metal pricing](https://www.latitude.sh/pricing). Cluster cost is the sum of its Node Pool Nodes. | ## Where the boundaries are > **Bare metal and Control Plane (Latitude.sh)** > > Latitude.sh runs the physical layer and the managed Control Plane. > > * **Hardware:** if a Node fails due to a hardware fault, Latitude.sh handles the physical remediation. > * **Control Plane:** the API server and etcd run as a managed, highly available service. You don't size, access, or patch Control Plane Nodes. > **Node Pools (shared)** > > You define each Node Pool's plan, size, Labels, and Taints; Latitude.sh provisions the bare metal and joins it to the Cluster. > > * **Images:** Node operating system images are Latitude.sh's. New images reach your Nodes when you upgrade or scale a Node Pool, or add a new one. > * **Capacity:** you decide how many Node Pools to run and how large each is. > **Day-2 operations (you)** > > You are the Cluster operator. > > * **Workloads and add-ons:** ingress controllers, storage drivers, and other add-ons are yours to install and maintain. > * **Upgrades:** you choose when to upgrade the Control Plane and each Node Pool. > * **Observability:** Latitude.sh won't alert you if your Pods are in `CrashLoopBackOff`. Run your own monitoring to catch Workload-level failures. ## LoadBalancer and BGP boundary When you create a `Service` of type `LoadBalancer` with `spec.loadBalancerClass: latitude.sh/elastic-ip`, Latitude.sh allocates a Latitude Elastic IP and announces it over BGP from your Cluster's Nodes. **What Latitude.sh provides** The address is allocated and reachable. BGP announces it from the Cluster, and the network fabric routes traffic to your Nodes. **What you own** * Creating the LoadBalancer Service and any Ingress or Gateway controller behind it. * Application-level behavior. If the IP is reachable at L4 but your app returns `404`, `502`, or connection refused, the cause is on your side: Service selectors, endpoints, ingress rules, or Pod readiness. See [Exposing Workloads](/docs/lks/exposing-workloads) and [LoadBalancer Services](/docs/lks/load-balancer-services). # Managed Databases Source: https://www.latitude.sh/docs/managed-databases Latitude.sh Managed Databases is a fully managed PostgreSQL database service that integrates with your infrastructure. It includes scheduled backups, IP-based access control, performance monitoring, and optional Supabase integration. ## Features | Feature | Supported | | - | - | | Database Monitoring | ✓ | | Scheduled Backups | ✓ | | Trusted Sources (IP filtering) | ✓ | | Database Parameters | ✓ | | Supabase Addon | ✓ | * **Database Monitoring**: Track CPU, memory, transaction throughput, and storage size over time. [Learn more](managed-databases/monitoring). * **Database Backups and Restoration**: Configure scheduled backups, view backup history, and restore data when needed. [Learn more](/docs/managed-databases/backups-and-restoration). * **Trusted Sources**: Control database access with IP-based restrictions. [Learn more](/docs/managed-databases/trusted-sources). * **Database Parameters**: Customize PostgreSQL and PgBouncer parameters to optimize your database for your specific workload. [Learn more](/docs/managed-databases/parameters). * **Supabase Addon**: Add Supabase functionality for auto-generated APIs and database management tools. [Learn more](/docs/managed-databases/supabase-addon). ## Creating a database **1. Access database creation** [Log in to the dashboard](https://www.latitude.sh/dashboard), select a project, navigate to **Databases** in the sidebar menu, and click **Create Database**. Select "New Database" on the database deployment page. **2. Configure database specifications** Choose a location and plan based on your requirements. Optionally, configure scheduled backups according to your backup requirements. Provide a name for your database. **3. Deploy the database** Click **Deploy** to create your database. ![Create database interface](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/26.Docs25Q4.CreateDB.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=866103f21cc75aa6f667abf3be7a886b) ## Additional documentation * [Database Monitoring](/docs/managed-databases/monitoring) - Monitor the performance and usage of your databases. * [Database Backups and Restoration](/docs/managed-databases/backups-and-restoration) - Configure and manage automated scheduled backups. * [Trusted Sources](/docs/managed-databases/trusted-sources) - Control database access with IP-based restrictions. * [Database Parameters](/docs/managed-databases/parameters) - Customize PostgreSQL and PgBouncer parameters for your workload. * [Supabase Addon](/docs/managed-databases/supabase-addon) - Optional Supabase functionality for enhanced developer experience. # Database Backups and Restoration Source: https://www.latitude.sh/docs/managed-databases/backups-and-restoration Latitude.sh Databases offers scheduled backups to S3-compatible storage, allowing you to protect your data and restore it when needed. Backups are a critical component of any production database strategy, ensuring business continuity and data protection. Restoring a database from a backup is a vital operation that allows you to recover your data in case of accidental deletion, corruption, or when you need to create a copy of an existing database. ## How backups work When you enable backups for your database: 1. Latitude.sh automatically creates full database backups according to your specified schedule. 2. Backups are stored in your specified S3-compatible storage location. 3. Backups are retained for the duration you configure. 4. You can restore from any available backup when creating a new database. ## Testing S3 connection Latitude.sh requires you to test your S3 connection before deploying a database with scheduled backups enabled. This ensures that your backups will run successfully and prevents deployment issues. ### How it works When you enable scheduled backups, the connection test validates that your S3 credentials have the necessary permissions by testing three essential operations: * **PUT**: Write backup files to your bucket * **GET**: Read backup files from your bucket * **DELETE**: Remove old backup files (retention policy) The test creates temporary files in your specified backup path and cleans them up afterward, ensuring your S3 configuration works with the exact operations that the backup system requires. ### Testing your connection #### In the database creation flow 1. After configuring your S3 backup settings, click **Test Connection**. 2. The system validates your credentials and permissions. 3. If successful, you'll see a success notification and can proceed with deployment. 4. If failed, review the specific error message and resolve the issue. #### In the database overview (existing databases) 1. Navigate to your database overview page. 2. Configure or modify your backup settings. 3. Click **Test Connection** before applying changes. 4. The **Apply** button becomes available only after a successful test. ### Connection test states * **Idle**: Ready to test connection * **Testing**: Validating S3 credentials and permissions * **Passed**: Connection successful, deployment/changes can proceed * **Failed**: Issues detected, must resolve before proceeding ### Common issues and solutions #### Authentication errors * **Error**: Invalid access credentials * **Solution**: Verify your S3 Access Key ID and Secret Access Key are correct #### Permission errors * **Error**: Missing required permissions * **Solution**: Ensure your S3 credentials have the minimum required IAM permissions: ```json theme={null} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"], "Resource": "arn:aws:s3:::your-bucket-name/your-backup-path/*" } ] } ``` #### Network connectivity errors * **Error**: Cannot reach storage endpoint * **Solution**: Verify your S3 endpoint URL is correct and accessible from your network #### Bucket/path access errors * **Error**: Bucket not found or path access denied * **Solution**: Confirm the bucket name is correct, verify the backup path exists and is accessible, and check that your IAM policy allows access to the specific path ### S3-compatible storage support The connection test works with all S3-compatible storage providers, including: * Amazon S3 * Backblaze B2 * Cloudflare R2 * DigitalOcean Spaces * MinIO * Wasabi * Other S3-compatible services Simply provide the correct endpoint URL for your storage provider. ### Important notes * Connection testing is mandatory when backups are enabled * The deploy button remains disabled until the test passes * Tests run instantly without requiring a database to be running * Temporary test files are automatically cleaned up after testing * If your credentials or settings change, you must retest the connection ## Configuring scheduled backups When creating a new database or modifying an existing one, you can enable and configure scheduled backups: 1. Click **Set up scheduled backup** when creating a database or navigate to the **Backups** tab for an existing database. 2. Enter the name of your **S3 bucket** and specify the backup path where the backups will be stored (E.g. `/backups`). 3. Provide your **S3 Endpoint**. 4. Enter your Access **Key ID** and **Secret Access Key**. 5. Use the Schedule (Cron) dropdown to set how often backups should run. For a custom schedule, enter a six-field cron expression (E.g. `0 0 3 * * *` for daily backups at 3 AM UTC). 6. In the **Retention** field, enter how many days backups should be kept (E.g. 30 days). 7. **Test your S3 connection** by clicking **Test Connection** to ensure your credentials and permissions are correctly configured. 8. Click **Save** (create a new database) or **Apply** (modify an existing database) to save the backup configuration (available only after successful connection test). Once enabled, you'll see a shield icon next to your database in the database list, indicating that backups are active. You can pause or resume backups at any time from the **Backups** tab by clicking the **Manage** button. ## Managing Backups To view and manage your database backups: 1. Navigate to **Databases** in the sidebar menu. 2. Select the database you want to manage backups for. 3. Click on the **Backups** tab on the database overview page. The Backups tab displays: * **Backup Configuration Details**: If backups are configured, you'll see information about your S3 storage settings, schedule, and retention period. * **Backup List**: A table showing all available backups with their creation date and status (Running, Completed, or Failed). * **Manage Button**: Click this button to configure, pause, resume, or modify your backup settings. ## Restoring a Database from a Backup Latitude.sh provides multiple intuitive ways to restore databases from backups, ensuring this functionality is easily accessible when you need it most, especially in critical situations. **Important:** Restoring a database from a backup **creates a brand new database instance**—it does not restore data into your existing database. Both the original and new databases will run simultaneously and be billed separately. After verifying your restored database works correctly, remember to delete the old database if you no longer need it to avoid duplicate charges. ### Prerequisites for Restoration Before you can restore a database from a backup: * You must have at least one database with backups configured. * At least one successful backup must have been created. * You need appropriate permissions to create databases in your project. ### Restoration Methods Latitude.sh offers multiple straightforward ways to restore a database from a backup: #### Method 1: From the Database List View The most direct way to restore a database from a backup is directly from the database list view: 1. Navigate to **Databases** in the sidebar menu to view your list of databases. 2. Find the database with the backup you want to restore from and click the actions menu (three dots) on the right side of its row. 3. Select **Restore from backup** from the dropdown menu. 4. Choose the specific backup point you want to restore from. 5. Provide a name for your new database. 6. Select a plan and specifications. Note that the plan must be equal to or higher than the source database's plan. 7. Click **Deploy** to start the restoration process. #### Method 2: From a Database's Backups Tab You can also initiate a backup restoration from a specific database's backups tab: 1. Navigate to **Databases** in the sidebar menu. 2. Click on the name of the database that has the backup you want to restore from. 3. Navigate to the **Backups** tab. 4. Find the backup you want to restore and click the **Restore** button. 5. Follow the prompts to select a specific backup, name your new database, and choose appropriate specifications. 6. Click **Deploy** to create the new database from the backup. #### Method 3: From the Backups tab 1. Navigate to **Databases** in the sidebar menu. 2. Select the database that has the backup you want to restore from. 3. Click on the **Backups** tab on the database overview page. 4. Find the backup you want to restore from in the backup list. 5. Click the **New from backup** button next to the backup (only available for completed backups). 6. Configure the new database as you would normally do when creating a new database. #### Method 4: From the Database Creation Flow You can also restore from a backup when creating a new database: 1. Navigate to **Databases** in the sidebar menu and click **Restore from backup**. 2. Select a **source database** and choose the backup you want to use. If no databases appear, ensure backups have been created. 3. Provide a name for your new database. 4. Choose a plan and specifications based on your requirements. Note that the selected plan must be equal to or higher than the source database plan. 5. Click **Deploy**. ### Important Considerations for Restoration When restoring a database from a backup, keep these points in mind: * **Both databases will run simultaneously**: The restoration process creates a new database; it does not overwrite the existing one. You will be billed for both databases until you delete one of them. * **Different connection string**: The new database will have a different connection string than the original. You must update your application configuration to use the new connection string. * **Typical workflow**: Restore to new database → verify data integrity → update your application to use the new connection string → delete the old database once confirmed everything works. * **Restoration time**: The restoration time depends on the size of the backup. * **Plan requirements**: The new database must use a plan equal to or higher than the source database's plan. * **Complete data restoration**: All data in the backup will be restored, including tables, indexes, and stored procedures. ## Backup and Restoration Best Practices For an optimal database backup and restoration strategy: 1. **Set appropriate frequency**: Configure backup frequency based on how much data you can afford to lose. Critical applications might require hourly backups, while less critical ones might be fine with daily backups. 2. **Test your backups and restoration**: Periodically create a test database from a backup to verify that your backups are working correctly and can be restored. Regularly testing your backup restoration process is recommended to ensure you can recover your data when needed. 3. **Secure your S3 credentials**: Ensure that the S3 credentials used for backups have appropriate permissions and are securely stored. 4. **Consider retention periods**: Set retention periods based on your compliance requirements and storage constraints. ## Troubleshooting If you encounter issues with your database backups or the restoration process: ### Backup Issues: 1. **Verify S3 credentials**: Ensure your S3 access key and secret key are correct and have appropriate permissions. 2. **Check S3 bucket existence**: Confirm that the specified S3 bucket exists and is accessible. 3. **Validate cron expression**: If using a custom schedule, verify that your cron expression is correctly formatted using a 6-field format. ### Restoration Issues: 1. **Ensure sufficient permissions**: Verify you have permissions to create databases in your project. 2. **Check for successful backups**: Confirm that the source database has successful backups available. 3. **Review database logs**: If the restoration fails, check the database logs for specific error messages. If you continue to experience issues with backups or restoration, contact Latitude.sh support for assistance. # Database Monitoring Source: https://www.latitude.sh/docs/managed-databases/monitoring Latitude.sh provides monitoring capabilities for your databases, allowing you to track performance metrics and understand resource utilization. This helps diagnose issues, optimize performance, and ensure database stability. ## Accessing Monitoring To access monitoring for any database: 1. Go to the **Databases** section in the sidebar menu. 2. Select the database you want to monitor. 3. View the **Monitoring** section on the overview page for a quick summary. 4. Click the **Monitoring** tab for detailed charts. ### Overview Page Metrics The database overview page displays real-time sparklines for: * **CPU Usage**: CPU utilization percentage * **Memory Usage**: Memory consumption percentage * **Transactions Per Second (TPS)**: Transaction throughput rate ### Monitoring Page The monitoring page provides detailed time-series charts: * **CPU Usage**: CPU utilization over time * **Memory Usage**: Memory consumption over time * **Transactions Per Second (TPS)**: Transaction rate over time * **Database Size**: Storage growth over time Use the period selector to adjust the time range for all charts, from 30 minutes to 7 days. ## Why storage matters PostgreSQL reserves approximately **5%** of disk space for Write-Ahead Log (WAL) operations—a critical mechanism for data integrity and crash recovery. When your database reaches **95% total disk usage**, WAL operations may fail, causing: * Connection disruptions * Transaction failures * Potential data loss Keep an eye on the **Database Size** chart on the Monitoring page so you can act before usage gets that high. ### Recommended actions If your database is approaching capacity: 1. **Upgrade your database plan** - Scale to a larger plan with more storage capacity from your database settings. 2. **Remove unused data** - Delete obsolete records, truncate logs, or archive historical data. 3. **Optimize storage** - Run `VACUUM FULL` to reclaim space from deleted rows, or review large tables for optimization opportunities. # Database Parameters Source: https://www.latitude.sh/docs/managed-databases/parameters Configure PostgreSQL and PgBouncer parameters for your database. Latitude.sh allows you to customize PostgreSQL and connection pooler parameters to optimize your database for your specific workload. You can configure these parameters from the Parameters tab in your database dashboard. ## PostgreSQL parameters The following PostgreSQL parameters can be customized based on your database plan. ### Connection parameters | Parameter | Description | | - | - | | **Max Connections** | Maximum number of concurrent database connections. Higher values allow more simultaneous clients but consume more memory. | | **TCP Keepalives Idle** | Seconds of inactivity before sending a TCP keepalive. 0 to use OS default. | | **TCP Keepalives Interval** | Seconds between TCP keepalive retransmits. 0 to use OS default. | | **TCP Keepalives Count** | Maximum TCP keepalive retransmits before considering connection dead. | ### Memory parameters | Parameter | Description | | - | - | | **Shared Buffers** | Memory allocated for PostgreSQL's shared buffer cache. This is where frequently accessed data is cached. Recommended: 25% of available RAM. | | **Work Memory** | Memory used per operation for sorting and hash tables. Be careful with high values as this is multiplied by concurrent operations. | | **Maintenance Work Memory** | Memory allocated for maintenance operations like VACUUM, CREATE INDEX, and ALTER TABLE. | | **Effective Cache Size** | The planner's estimate of available memory for disk caching. This helps PostgreSQL choose better query plans. | | **Temp File Limit** | Maximum disk space for temporary files per session. -1 for unlimited. | ### Timeout parameters | Parameter | Description | | - | - | | **Idle Transaction Timeout** | Time before idle transactions are automatically terminated. Prevents connections from being held indefinitely. | | **Idle Session Timeout** | Time before idle sessions are terminated. 0 to disable. | | **Statement Timeout** | Maximum time a query can run before being cancelled. Useful for preventing runaway queries. Set to 0 to disable. | | **Lock Timeout** | Maximum time to wait for a lock. Prevents queries from waiting indefinitely for locked resources. Set to 0 to disable. | ### WAL & Checkpoint parameters | Parameter | Description | | - | - | | **Max WAL Size** | Maximum size the WAL can grow to between checkpoints. | | **Min WAL Size** | Minimum size of WAL files to retain. | | **WAL Buffers** | Shared memory used for WAL data not yet written to disk. | | **Checkpoint Timeout** | Maximum time between automatic WAL checkpoints. | | **Checkpoint Completion Target** | Target completion fraction of checkpoint. Higher values spread I/O over time. | ### Autovacuum parameters | Parameter | Description | | - | - | | **Vacuum Scale Factor** | Fraction of table size to add to vacuum threshold. | | **Analyze Scale Factor** | Fraction of table size to add to analyze threshold. | | **Autovacuum Naptime** | Time between autovacuum runs. | ## Connection pooler (PgBouncer) PgBouncer is a connection pooler that sits between your application and PostgreSQL. It efficiently manages database connections, reducing overhead and improving performance. ### Pool settings | Parameter | Description | | - | - | | **Pool Mode** | How connections are assigned to clients. **Transaction** mode (recommended) releases connections after each transaction. **Session** mode keeps connections for the session lifetime. **Statement** mode releases after each statement. | | **Default Pool Size** | Number of server connections maintained per user/database pair. | | **Min Pool Size** | Minimum server connections to keep open per pool. | | **Reserve Pool Size** | Additional connections for reserve pool when default is exhausted. | ### Connection limits | Parameter | Description | | - | - | | **Max Client Connections** | Maximum number of client connections the pooler accepts. | | **Max DB Connections** | Maximum connections allowed per database. | ### Timeouts | Parameter | Description | | - | - | | **Query Timeout (s)** | Maximum time a query can run. 0 to disable. | | **Query Wait Timeout (s)** | Maximum time a client can wait for a server connection. | | **Server Idle Timeout (s)** | Time a server connection can be idle before being closed. | | **Client Idle Timeout (s)** | Time a client connection can be idle. 0 to disable. | | **Server Connect Timeout (s)** | Maximum time to establish a server connection. | ## Recommended defaults Default values are optimized for each database plan to provide stable operation within your plan's resources. You have full control over parameter values, but we recommend staying close to these defaults unless you have specific requirements. **Small** | Parameter | Default | | - | - | | Max Connections | 100 | | Shared Buffers | 128MB | | Work Memory | 16MB | | Maintenance Work Memory | 64MB | | Effective Cache Size | 1GB | | Pool Size | 20 | | Max Client Conn | 100 | **Medium** | Parameter | Default | | - | - | | Max Connections | 200 | | Shared Buffers | 256MB | | Work Memory | 32MB | | Maintenance Work Memory | 128MB | | Effective Cache Size | 2GB | | Pool Size | 30 | | Max Client Conn | 200 | **Large** | Parameter | Default | | - | - | | Max Connections | 1000 | | Shared Buffers | 512MB | | Work Memory | 128MB | | Maintenance Work Memory | 256MB | | Effective Cache Size | 4GB | | Pool Size | 50 | | Max Client Conn | 500 | > [!WARNING] > > Values significantly outside recommended ranges will be highlighted in the > dashboard. While you can set any value, extreme settings may impact database > stability or performance. ## Configuring parameters 1. Go to **Databases** and select your database. 2. Click the **Parameters** tab. 3. Click **Manage** next to PostgreSQL or Pooler parameters. 4. Click on any parameter row to expand it and view the input field and allowed range. 5. Adjust the value as needed. A warning indicator appears if the value is outside the recommended range. 6. Click **Restore defaults** to reset all parameters to plan defaults, or **Apply** to save your changes. > [!NOTE] > > Parameter changes trigger a rolling restart of your database pods. This > ensures the new configuration is applied safely with minimal downtime. ## Best practices * **Start with defaults**: The default values are tuned for typical workloads. Only adjust if you have specific requirements. * **Monitor after changes**: Watch your database metrics after making parameter changes to ensure the desired effect. * **Work Memory caution**: High `work_mem` values can cause memory issues since this is allocated per operation. Calculate: `work_mem × max_connections × average_operations`. * **Use connection pooling**: For applications with many short-lived connections, the connection pooler significantly reduces overhead. * **Transaction mode**: Use transaction pool mode unless your application requires session-level features like prepared statements or advisory locks. # Supabase Addon Source: https://www.latitude.sh/docs/managed-databases/supabase-addon The Supabase addon integrates your Latitude.sh database with Supabase, providing auto-generated APIs and direct database management tools such as a table editor and SQL editor, all running on top of your existing PostgreSQL database. ## Enabling the Supabase Addon The Supabase addon can only be enabled for an existing database. It cannot be configured during the initial database creation process. To enable the Supabase addon: 1. Navigate to the **Databases** section in your Latitude.sh dashboard. 2. Select the database for which you want to enable the Supabase addon. 3. Click on the **Supabase** tab on the database overview page. 4. Click the **Enable Supabase Addon** button. ## After Enabling Once the Supabase addon is successfully enabled, you will be provided with two important API keys: * **`API_ANON_KEY`**: This is the anonymous public key. It's intended for client-side usage, for example, when using the Supabase client library in your frontend application. This key has limited permissions as defined by your Row Level Security (RLS) policies. * **`API_SERVICE_ROLE_KEY`**: This is the service role key. It's intended for server-side usage, such as in your backend services or scripts. This key has full access to your database and can bypass Row Level Security (RLS) policies. **Treat this key like a password and keep it secure.** After enabling the addon, the "Enable Supabase Addon" button will change to an **Open dashboard** link. Clicking this link will take you directly to your Supabase project dashboard associated with this database. ## Accessing the Supabase Dashboard Once the Supabase integration is enabled, there are two ways to access the Supabase dashboard: 1. **Open Dashboard Link**: After enabling the addon, the button in the **Security & Integrations** tab transforms into an "Open dashboard" link. 2. **Supabase Button**: You will find a dedicated **Supabase** button in the **Security & Integrations** tab. Clicking this button will also navigate you to the Supabase project dashboard. This provides convenient access to the Supabase dashboard where you can use features such as the table editor and SQL editor, and manage your Supabase API access. ## Troubleshooting If you encounter issues with the Supabase addon: 1. **Verify API Key Usage**: Ensure you are using the correct Supabase API keys (`API_ANON_KEY` for client-side, `API_SERVICE_ROLE_KEY` for server-side) and that they are correctly implemented in your application. 2. **Check Network Connectivity**: Confirm that your application can reach the Supabase endpoint associated with your database. 3. **Review Database Logs**: Check your database logs for any error messages that might indicate issues with the Supabase integration or underlying database operations. 4. **Consult Supabase Documentation**: For issues related to Supabase-specific features or client libraries, the [official Supabase documentation](https://supabase.com/docs) can be a valuable resource. If you continue to experience issues with the Supabase addon, contact Latitude.sh support for assistance. # Trusted Sources Source: https://www.latitude.sh/docs/managed-databases/trusted-sources Trusted Sources is a security feature for Latitude.sh Databases that allows you to control which IP addresses can connect to your database. This feature helps enhance your database security by limiting access to known and trusted IP addresses. ## Understanding Trusted Sources When you enable Trusted Sources for your database: * You can specify which IP addresses or CIDR ranges are allowed to connect. * Connection attempts from IP addresses not on your allowed list will be rejected. * This provides an additional security layer alongside your database's authentication mechanisms. This feature is useful for: * Limiting database access to only your application servers. * Restricting connections to specific office or development environments. * Reducing your database's exposure to potential unauthorized access attempts. ![Database trusted sources configuration](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/27.Docs25Q4.DBtrustedSources.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=ea3e0062d7c15190e1444f3e2169dd4a) ## Enabling and configuring Trusted Sources To configure Trusted Sources: 1. Navigate to the **Databases** section in your Latitude.sh dashboard. 2. Select the database you want to configure. 3. Click the **Settings** tab. 4. Find the **Trusted Sources** section. 5. Enter the IP addresses or CIDR ranges to allow. For example: `203.0.113.1` for a single IPv4, `203.0.113.0/24` for an IPv4 range, or `2001:db8::/32` for IPv6. 6. Add multiple entries as needed, one per line. 7. Click **Save** to apply your configuration. Once enabled, a fingerprint icon appears next to your database in the list. ## Important considerations When using Trusted Sources, keep these important points in mind: 1. **Test carefully before enabling in production**: Always verify that your application servers and development environments can connect after enabling. 2. **Include all necessary IPs**: Make sure to include all IP addresses that legitimately need access, including: * Your application servers. * CI/CD systems that run database migrations. * Development environments. * Database administration tools. 3. **Dynamic IP considerations**: If you're connecting from environments with dynamic IPs (like home networks), you may need to update your Trusted Sources configuration when your IP changes. 4. **Backup access plan**: Have a plan for updating your Trusted Sources configuration if your server IPs change or if you need to access the database from a new location. ## Troubleshooting If you're having trouble connecting to your database after enabling Trusted Sources: 1. **Verify your current IP**: Check your current public IP address (you can use services like [whatismyip.com](https://www.whatismyip.com/)) and ensure it's included in your allowed list. 2. **Check for IP changes**: If you're connecting from a dynamic IP environment, your IP may have changed since you configured Trusted Sources. 3. **Verify CIDR notation**: If using CIDR notation, ensure it's correctly formatted (e.g., `192.168.1.0/24`). 4. **Temporarily disable for testing**: If needed, you can temporarily disable Trusted Sources to verify if it's causing your connection issues. If you're locked out of your database due to Trusted Sources configuration, contact Latitude.sh support for assistance. # BYOIP Source: https://www.latitude.sh/docs/networking/byoip Bring your own IPv4 address prefixes to Latitude.sh infrastructure BYOIP (Bring Your Own IP) lets you use your own IPv4 address prefixes on Latitude.sh infrastructure instead of Latitude.sh-assigned addresses. ## Use cases * **IP reputation preservation:** Keep your established IP reputation when migrating to Latitude.sh. * **Compliance requirements:** Meet regulatory requirements that mandate specific IP ranges. * **Brand consistency:** Maintain IP addresses associated with your organization. * **Migration flexibility:** Move workloads without changing public-facing IP addresses. ## Requirements Before requesting BYOIP, you need: * **IP address prefix:** A publicly routable IPv4 address range in CIDR notation (e.g., `203.0.113.0/24`). * **RIR registration:** The prefix must be registered with a Regional Internet Registry (ARIN, RIPE NCC, APNIC, LACNIC, or AFRINIC). * **Route objects:** Route objects created for all prefixes you want to announce. * **RPKI validation:** RPKI should be valid for all prefixes. * **Authorization:** You must be able to prove ownership of the IP prefix. ## Requesting BYOIP **1. Navigate to IP addresses** Select a project and go to **Network → IP addresses**, then select the **BYOIP** tab. **2. Click Request BYOIP** Click the **Request BYOIP** button to open the request form. **3. Enter prefix information** Provide details about the IP prefixes you want to bring to Latitude.sh: * **Regional Internet Registry (RIR):** Select where your prefix is registered. * **Announcement site:** Select the Latitude.sh site where the prefix should be announced. * **Already announced:** Indicate whether you already have a prefix announced on this site. * **Prefixes:** List all prefixes in CIDR notation, one per line (e.g., `203.0.113.0/24`). * **Route objects:** Confirm whether route objects are created for all prefixes. * **RPKI:** Confirm whether RPKI is valid for all prefixes. **4. Select a deploy type** Choose how the prefix should be deployed on Latitude.sh infrastructure: * **BGP Session:** Establishes a BGP session between your machine and our router. * **Static Route:** Creates a static route to your machine. * **VLAN (HSRP/VRRP):** Sets up the prefix gateway on Latitude.sh infrastructure using VLAN with HSRP/VRRP. See [Deploy types](#deploy-types) for details on each option. **5. Provide deployment details** Depending on your selected deploy type, provide the required deployment details: * **BGP Session:** Select the server for the BGP peer, choose a route preference (full route, default route, or both), and enter your ASN. * **Static Route:** Select the server for the static route destination, enter your ASN, and optionally upload a Letter of Authorization (LOA). * **VLAN:** List the machines that will use these prefixes, enter your ASN, and optionally upload a Letter of Authorization (LOA). **6. Submit the request** Optionally add a use case description, then click **Submit Request**. After you submit your request, the Network Operations team will review it and contact you with next steps. ## Deploy types Choose how your prefix will be deployed when requesting BYOIP. ### BGP Session Establishes a BGP session between your machine and the Latitude.sh router. **Advantages:** * You can choose to receive full route or default route. * You can control your incoming traffic using BGP communities. * None of your IPs will be on any part of the Latitude.sh network. **Limitations:** * You can only use your prefix on the server where the BGP session is established. ### Static Route Creates a static route pointing to your machine. **Advantages:** * Simple to configure. * None of your IPs will be on any part of the Latitude.sh network. **Limitations:** * You can only use your prefix on the server that the static route points to. ### VLAN (HSRP/VRRP) Sets up the prefix gateway on Latitude.sh infrastructure using a VLAN with HSRP/VRRP. **Advantages:** * Simple to configure. * Multiple servers can use IPs from this prefix by tagging the VLAN on the server's interface. **Limitations:** * Latitude.sh requires 3 IPs from each prefix (x.x.x.1, x.x.x.2, and x.x.x.3) for the HSRP/VRRP gateway. # Cloud Gateway Source: https://www.latitude.sh/docs/networking/cloud-gateway Cloud Gateway establishes a private, secure, and direct connection between your Latitude.sh servers and major cloud providers. To connect Latitude.sh's infrastructure to your cloud provider's resources, log in to the [dashboard](https://www.latitude.sh/dashboard), select a project, then navigate to **Interconnection > Cloud Gateway** in the sidebar. Complete the required fields to submit your request. Once submitted, the team will handle the configurations. ![Cloud Gateway interface](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/31.Docs25Q4.CloudGateway.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=a2a04222b521ce8047cee4d65c6f643e) **Connecting to AWS** **1. Configure connection details** Choose the location of your Latitude.sh server from which you want to establish the connection to AWS. Optionally, select a [private network](/docs/networking/private-networks) if one is configured. Enter the IP address range in CIDR format. The IP prefix is associated with your on-premises network and needs to be routable to AWS. **2. Set up AWS configuration** Select AWS as the destination cloud provider and enter the AWS region where your [Virtual Private Cloud (VPC)](https://aws.amazon.com/vpc/) or other resources are hosted. You can find this information in the top right corner of the [AWS Management Console](https://aws.amazon.com/console/). Enter your 12-digit AWS account ID from the **My Account** section in the [AWS Management Console](https://aws.amazon.com/console/). Enter your Amazon Autonomous System Number (ASN), found in the [AWS Direct Connect Console](https://console.aws.amazon.com/directconnect/home) under Virtual Interfaces. If you don't have a virtual interface, create one through the Direct Connect setup process. See the [AWS Direct Connect User Guide](https://docs.aws.amazon.com/directconnect/latest/UserGuide/accepthostedvirtualinterface.html) for more information. **3. Complete the request** Choose the desired port speed for your connection from the available options. Once all fields are completed, click **Request**. **Canceling the connection to AWS** To cancel the connection between Latitude.sh and AWS, follow these steps: **1. Cancel AWS connection** Log in to your AWS account and remove the connection associated with Cloud Gateway. Next, go to **Support** in the [dashboard](https://www.latitude.sh/dashboard) and create a **New ticket** to request service cancellation. The connection will be terminated once both steps are completed and the team processes your request. **Connecting to GCP** **Step 1** Choose the location of your Latitude.sh server from which you want to establish the connection to GCP. **Step 2** Select a [private network](/docs/networking/private-networks) if one is configured (optional). **Step 3** Enter the IP address range in CIDR format. The IP prefix is associated with your on-premises network and needs to be routable to GCP. **Step 4** Select GCP as the destination cloud provider. **Step 5** Enter the GCP region where your resources are hosted. **Step 6** Log in to your [Google Cloud Console](https://console.cloud.google.com/) and create a pairing key. **Creating a pairing key** **Step 1** From the main menu in the Google Cloud Console, select **Hybrid Connectivity > Interconnect**. ![GCP-project1](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/gcp-project1.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=74d3b5149c87508b72f606a757dde478) **Step 2** Click **Get Started**. **Step 3** Select Partner Interconnect and click **Continue**. ![Partner-interconnect](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/gcp-partner-interconnect.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=aa8dc2b1b8578dc2f159e1defdf867c6) **Step 4** Click **I already have a service provider**. ![Already-have-a-sp](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/gcp-service-provider.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=33b55453a6fd4f43e96b3c6b6e5ae751) **Step 5** Configure your attachment. ![vlan-attachment](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/gcp-vlan-attachment.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=4d64f261cbe1fc3dc12938c95bebdd5b) **Step 6** Provide the following details: * **Redundancy**: Review the options for redundancy and select. You can create redundant Attachments or a single Attachment. * **Network**: Select the VPC network you want your VPC to connect to. * **Region**: Select the region where your attachment will connect. * **Cloud Router**: A Cloud Router to associate with this attachment. You can only choose a Cloud Router in the VPC network and region that you selected with an ASN of 16550. If you don't have an existing Cloud Router, create one with an ASN of 16550. For redundancy, each VLAN attachment must be associated with a unique Cloud Router. Google automatically adds an interface and a BGP peer on the Cloud Router. * **VLAN attachment name**: Lowercase letters only. * **Description** (optional). * **Maximum Transmission Unit (MTU)**: To use the 1500-byte MTU, the VPC network using the attachment must have an MTU set to 1500. In addition, the on-premises VMs and routers must have an MTU set to 1500. If your network has the default MTU of 1460, leave the field at 1440. **Step 7** Click **Create**. **Step 8** Copy the pairing key and click **OK**. ![pairing-key](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/gcp-pairing-key.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=3c2fca3499bad40c9fb879e1fca242ac) **Step 9** Go back to the Cloud Gateway form and paste the copied pairing key into the **Pairing Key** field. **Step 10** Choose the desired port speed for your connection from the available options. **Step 11** Once all fields are completed, click **Request**. **Connecting to Azure** **Step 1** Choose the location of your Latitude.sh server from which you want to establish the connection to Azure. **Step 2** Select a [private network](/docs/networking/private-networks) if one is configured (optional). **Step 3** Enter the IP address range in CIDR format. The IP prefix is associated with your on-premises network and needs to be routable to Azure. **Step 4** Select Azure as the destination cloud provider. **Step 5** Enter the [Azure region](https://learn.microsoft.com/en-us/azure/devops/organizations/accounts/change-organization-location?view=azure-devops) where your resources are hosted. **Step 6** Enter the service key from your [ExpressRoute circuit](https://learn.microsoft.com/en-us/azure/expressroute/expressroute-howto-circuit-portal-resource-manager). To generate one, create an ExpressRoute connection in the Azure Portal and deploy the circuit. **Step 7** Choose the desired port speed for your connection from the available options. **Step 8** Once all fields are completed, click **Request**. # DDoS protection Source: https://www.latitude.sh/docs/networking/ddos-protection Latitude.sh builds and manages its [DDoS Protection](https://www.latitude.sh/ddos-protection) infrastructure instead of offloading it to a third-party service. This means Latitude.sh has full control and visibility over denial-of-service attacks coming into the infrastructure and takes proactive actions to mitigate attacks before they impact your services With 7 Tbps of capacity, Latitude.sh's scrubbing centers are equipped to handle any distributed attack, no matter its shape or form. Latitude.sh's DDoS Protection can handle all known types: **Network Level** * TCP Flood * UDP Flood * ICMP Flood **Reflective/Amplified** * DNS Flood * NTP Flood * SNMP Flood * SSDP Flood **Fragmented Packet** * Overlapping * Missing * Too Many **Application Layer** * Repetitive GET * Slowloris * SlowRead **Specially Crafted Packet** * Stack * Protocol * Buffer ## Pricing DDoS Protection is included free of charge with all servers based on the [Fair Usage Policy](https://www.latitude.sh/legal/fair-usage). Latitude.sh does its best to mitigate all attacks while ensuring the network isn't impacted. If at any point the attack is larger than the available capacity, and if there's a risk of compromising the network and other customers, the affected IP might be null-routed, which essentially means that the IP or IPs being attacked are placed on a route that leads nowhere for a specific amount of time, usually two hours. # Elastic IPs Source: https://www.latitude.sh/docs/networking/elastic-ips Create and manage portable IP addresses that can be moved between servers in your project Elastic IPs are portable public IPv4 /32 addresses that you create on demand, assign to a server, and move to another server within the same project. Unlike [Additional IPs](/docs/networking/ips), which require a support request and manual approval, Elastic IPs are fully self-service. > [!NOTE] > > Elastic IPs are currently only supported for **bare metal servers**. Virtual machine support is not yet available. Elastic IPs are billed monthly. See the [networking pricing page](https://www.latitude.sh/pricing/networking#ips) for current rates. Elastic IPs are scoped to a project. To access them, first select a project from the dashboard, then navigate to **Network → IP addresses** in the sidebar. ## Use cases * **High availability:** reassign an IP to a standby server during failover. * **Blue/green deployments:** point traffic to a new server without DNS changes. * **Flexible infrastructure:** allocate and release IPs as your needs change. ## Limits Each team can have up to **5 Elastic IPs** by default. [Contact support](https://www.latitude.sh/dashboard/support) to request an increase. ## Creating an Elastic IP > [!NOTE] > > Elastic IPs are not available in the **São Paulo (SAO)** location. Additionally, some servers in other locations may have a legacy network topology that is not compatible with Elastic IPs. If you encounter this, please [contact support](https://www.latitude.sh/dashboard/support) for assistance. **1. Navigate to IP addresses** In the sidebar, go to **Network → IP addresses** and select the **Elastic IPs** tab. **2. Click Create Elastic IP** Click the **Create Elastic IP** button. **3. Select routing type and server** Choose the routing type (**Routed** is the default) and select the target server you want to assign the IP to. > [!NOTE] > > Need one address served by multiple servers for high availability? See [Elastic IPs via BGP](/docs/networking/elastic-ips-bgp). **4. Wait for provisioning** The IP will show a status of **Configuring** until provisioning completes. ## Moving an Elastic IP **1. Open the Elastic IP details** From the Elastic IPs list, click on the IP you want to move. **2. Edit the assigned server** In the **Assigned server** section, click the edit icon next to the current server. **3. Select the new server and click Move** Choose the new target server (it must be in the same project) and click **Move**. **4. Wait for reassignment** The IP will show a status of **Moving** until the reassignment completes. ## Deleting an Elastic IP **1. Open the actions menu** From the Elastic IPs list, find the IP you want to delete and open its actions menu. **2. Click Delete** Click **Delete** and confirm the deletion. **3. IP is released** The IP will briefly show a status of **Releasing**, then be removed. ## API reference You can also manage Elastic IPs programmatically using the API. See the [Elastic IPs API reference](https://www.latitude.sh/docs/api-reference/list-elastic-ips) for available endpoints. # Elastic IPs via BGP Source: https://www.latitude.sh/docs/networking/elastic-ips-bgp Announce a portable IP address from one or more of your own servers over BGP for high availability BGP mode is an alternative way to deliver an [Elastic IP](/docs/networking/elastic-ips). Instead of the network routing the address to a single assigned server, **your servers announce the address themselves over BGP**. Because more than one server can announce the same address at the same time, you can build high availability and distribute traffic across several servers without moving the IP by hand. > [!NOTE] > > BGP mode isn't available at every site — you can announce a BGP Elastic IP only from sites that support it. ## BGP mode vs. Routed mode In **Routed mode** (the default), the address is assigned to one server and the network forwards traffic to it. You move the address between servers from the dashboard. In **BGP mode**, the address is not tied to a server. You allocate a `/32` in a site, then each participating server runs a BGP session and announces the address. The network delivers traffic to the servers that are currently announcing it, so: * If an announcing server stops, traffic continues to the others — failover is automatic. * Traffic is distributed across the healthy servers that announce the address. You keep control of when the address is reachable: an announcement only exists while your server is up and announcing it. ## When to use BGP mode * **High availability** — run the same service on multiple servers so a single server failure does not take the address offline. * **Horizontal scale** — spread incoming traffic across several servers announcing the same address. If you only need to point one address at one server and occasionally move it, use Routed mode instead — it needs no configuration on the server. ## Requirements * **Bare metal servers only.** Virtual machine support is not available. * **IPv4 only.** * **Announcing servers must be BGP-ready.** Only servers that are compatible with BGP can announce a BGP Elastic IP. You enable this when you deploy the server — see [Deploy a BGP-ready server](#deploy-a-bgp-ready-server). Servers that aren't BGP-ready won't be available to add as announcers. * **Announcing servers must be in the same site as the address.** A `/32` allocated in a given site can only be announced by servers in that same site. The site you choose at allocation time is permanent. ## Deploy a BGP-ready server Only BGP-ready servers can announce a BGP Elastic IP. Enable this when you create the server — you can't add a server that isn't BGP-ready as an announcer. **1. Start creating a server** Go to **Compute → Servers**, click **Deploy server**, and configure it as usual (site, plan, operating system). **2. Enable BGP-ready server** In the **Advanced** section, turn on **BGP-ready server**. This allows the server to announce a shared Elastic IP for high availability. ![Advanced server options with the BGP-ready server toggle](https://mintcdn.com/latitudesh/UD2eDaWD5z-Tpe9I/images/product/bgp-ready-server-option.png?fit=max\&auto=format\&n=UD2eDaWD5z-Tpe9I\&q=85\&s=3bfba7ef9be2bba60f04459edebd0227) Deploy the server in the **same site** as the Elastic IP you plan to announce. ## Allocate a BGP Elastic IP **1. Navigate to IP addresses** In the sidebar, go to **Network → IP addresses** and select the **Elastic IPs** tab. **2. Click Create Elastic IP** Click the **Create Elastic IP** button and choose **BGP** as the routing type. **3. Select a site** Choose the **site** where the address will live. The site is permanent: only servers in this site will ever be able to announce the address, so pick the site where your servers are. **4. Wait for provisioning** The address is allocated immediately. It exists but is **not reachable yet** — nothing announces it until you add an announcing server and configure it. ## Add announcing servers An **announcing server** runs a BGP session and announces the address. Manage them from the Elastic IP detail page. **1. Open the Elastic IP details** From the Elastic IPs list, click the BGP-mode address. **2. Add an announcing server** In the **Announcing servers** section, pick a server from the **Select server...** dropdown, then click **Add server**. Only [BGP-ready servers](#deploy-a-bgp-ready-server) in the address's site are offered. The session starts as **pending** and becomes **active** once the network configuration is applied, usually within a few seconds. **3. Find the peer address** Each session has a **peer address** — the BGP neighbor your server peers with. On Latitude's network this is your server's gateway. You need it for the BIRD `neighbor` (or MetalLB `peerAddress`) in the next section. Get it in any of these ways: * **Dashboard** — the **Announcing servers** table shows a **Peer address** column for each server. * **API** — the session's `peer_address` field, returned by [List BGP sessions](https://www.latitude.sh/docs/api-reference/list-elastic-ip-bgp-sessions). It is `null` until the session becomes active. * **On the server** — it is your default gateway: ```bash theme={null} ip -4 route show default # default via dev eno1 ... ``` > [!NOTE] > > Removing an announcing server withdraws its announcement immediately. If you remove the only one, the address stops being reachable. ## Configure your server Adding an announcing server prepares the network side. Your server still has to (1) hold the address locally and (2) announce it over BGP. The examples below use **BIRD** on Ubuntu; adapt the paths to your distribution. Replace the placeholders throughout: * `` — the address you allocated. * `` — the session's peer address (your server's gateway). Find it in the dashboard's **Announcing servers** table, the session's `peer_address` field from [List BGP sessions](https://www.latitude.sh/docs/api-reference/list-elastic-ip-bgp-sessions), or with `ip -4 route show default`. * `` — your server's primary IPv4 address. ### 1. Bind the address to the loopback interface The server must own `` locally, on `lo`, so BIRD has a route to announce. Add it in a dedicated netplan file so it survives reboots: ```yaml /etc/netplan/99-elastic-ip.yaml theme={null} network: version: 2 ethernets: lo: addresses: - /32 ``` Set restrictive permissions and apply it: ```bash theme={null} sudo chmod 600 /etc/netplan/99-elastic-ip.yaml sudo netplan apply sudo networkctl reconfigure lo ``` > [!NOTE] > > `netplan apply` persists the address for the next boot but does **not** add it to the running loopback interface. Run `networkctl reconfigure lo` to add it now, then confirm with `ip addr show lo`. Use a **separate** file (`99-elastic-ip.yaml`), not `50-cloud-init.yaml`, which can be regenerated and would drop your change. ### 2. Install and configure BIRD ```bash theme={null} sudo apt update && sudo apt install -y bird2 ``` BIRD announces the address to your peer over BGP. It imports nothing and exports only the one `/32`: ```conf /etc/bird/bird.conf theme={null} router id ; protocol device { } # Picks up /32 from the loopback interface so it can be announced. # The ipv4 channel is required — without it BIRD imports no routes and nothing is announced. protocol direct { ipv4; interface "lo"; } protocol bgp latitude { local as 65512; neighbor as 65512; # Fail over quickly if this server becomes unresponsive. hold time 9; keepalive time 3; ipv4 { import none; export filter { if net = /32 then accept; reject; }; }; } ``` Reload BIRD to apply the configuration: ```bash theme={null} sudo birdc configure ``` ### 3. Verify the announcement ```bash theme={null} sudo birdc show protocols all latitude ``` The session should be **Established** and export exactly **one** route: ``` Routes: 0 imported, 1 exported BGP state: Established ``` `1 exported` confirms your server is announcing the address and the network accepted it. Repeat these steps on every announcing server you added. ## Recommended reliability practices BGP delivers traffic to whichever servers are announcing the address. Two additions make failover fast and correct. ### Tune the BGP timers The `hold time 9; keepalive time 3;` lines in the configuration above are the single most important reliability setting. With BIRD's defaults, a server that freezes with its link still up can keep attracting traffic for **two to three minutes** before the network gives up on it. With these timers, that drops to about **five seconds**. The lower value from either end wins, so setting it on your side is enough. ### Add an application liveness watchdog BGP only checks that the routing session is alive — not that your application is serving. If your application stops while BIRD keeps announcing, that server keeps receiving traffic it can no longer handle. Run a watchdog that checks your application and **removes `` from `lo`** when it stops responding: ```bash theme={null} sudo ip addr del /32 dev lo ``` Because the address is gone from `lo`, the `direct` protocol withdraws it and the network stops sending traffic to this server — while the BGP session itself stays up, so nothing churns. Restore the address when the application recovers and the announcement returns automatically. ## API reference You can manage BGP-mode Elastic IPs and their announcing servers programmatically. See the [Elastic IPs API reference](https://www.latitude.sh/docs/api-reference/list-elastic-ips) for available endpoints. # Firewall Source: https://www.latitude.sh/docs/networking/firewall Latitude.sh Firewall provides centralized management of resource-level *iptables* rules across your infrastructure. Unlike network firewalls that operate at the perimeter, it runs directly on each protected resource — servers and virtual machines — while letting you configure all firewall rules from a single interface. > [!WARNING] > > Latitude.sh Firewall requires an operating system that supports UFW > (Uncomplicated Firewall). Make sure your server is running a compatible OS > before attempting to install and use the firewall service. ## Creating a firewall Follow these steps to create a firewall: **1. Create a firewall** [Log in to the dashboard](https://www.latitude.sh/dashboard), select a project, navigate to **Firewall** in the sidebar menu, and click **Create Firewall**. Provide a name for your firewall and click **Create**. ## Navigating a firewall After you create a firewall, Latitude.sh opens the firewall detail page with a tabbed layout: * **Overview**: Summary, rule preview, protected resources preview, and agent installation commands * **Rules**: Create and edit inbound/outbound rules * **Resources**: Assign or remove protected servers and virtual machines * **Settings**: Delete the firewall The right-side **Details** panel shows firewall properties (name, rule count, resource count, tags, ID, and project) — you can also edit its tags here, and rename the firewall from the **Name** field. ## Setting firewall rules After creating a firewall, follow these steps to add rules for inbound and outbound traffic: **1. Add and configure firewall rules** Open the **Rules** tab, click **New rule**, and configure the rule settings: • **From**: Search/enter the source IP or select "Any" for all IPs. • **To**: Search/enter the destination IP or select "Any". • **Protocol**: Choose TCP or UDP. • **Port range**: Enter a single port or a range using a hyphen (for example, 22 or 80-443). • **Description**: (Optional) Add a label to make the rule easier to identify (e.g., "Allow SSH from office"). Click **Apply** to save your changes. > [!NOTE] > > Latitude.sh Firewall is built on UFW and only exposes **TCP** and **UDP** rules. **ICMP traffic is permitted by default** via UFW's preloaded rules, so you don't need (and can't create) an ICMP rule. Port range must be between **1 and 65535**. > [!NOTE] > > Every firewall includes a default rule that allows inbound SSH — **TCP on port 22** — from any source. Latitude.sh adds it automatically so you don't lose SSH access when you assign a firewall to a server. It's shown with a **Default** badge to identify it, and any rules you add appear alongside it. > [!WARNING] > > Removing SSH access can lock you out of a protected server. This happens if you delete the only rule that allows SSH, or if you assign a firewall that has no SSH-allowing rule. Verify that a firewall retains an SSH-allowing rule before assigning it to a server. ## Assigning a firewall to resources You can assign a firewall to a server or virtual machine either from the Firewall detail page or from the resource's own page: ### From the Firewall detail page **1. Assign the firewall to resources** Open the **Resources** tab and use the picker to add a server or virtual machine to protect. The picker searches both servers and virtual machines in the current project. A virtual machine that another firewall already protects can't be selected. The assigned list shows each resource's type — server or virtual machine — and links to that resource's detail page. **2. Install or uninstall the firewall agent** Open the **Overview** tab, expand **Agent Installation**, and copy the **Install** or **Uninstall** command. Run the command on each server or virtual machine to apply or remove the Latitude.sh firewall agent configuration. ### From the Server pages **1. Assign firewall from server page** Navigate to your server's **Overview** or **Network** page and locate the **Firewall assignments** section. Click **Assign** to select from existing firewalls in your project, or create a new firewall directly from this interface. To remove a firewall assignment, click the delete icon next to the assigned firewall in the **Firewall assignments** section. ### From the Virtual machine page **1. Assign firewall from the virtual machine page** Go to the virtual machine's **Overview** page and use the **Firewall assignment** section to assign a firewall. A virtual machine can be protected by only one firewall at a time — a limit specific to virtual machines — so once one is assigned the picker is no longer offered. To remove the assignment, use the same **Firewall assignment** section. > [!NOTE] > > Managing firewall assignments from server and virtual machine pages provides > the same functionality as the centralized Firewall dashboard. ## Renaming a firewall **1. Rename the firewall** Edit the **Name** field in the right-side **Details** panel, or use **Actions > Rename**. ## Firewall tags You can tag a firewall from its detail page using the tag editor in the **Details** panel. The firewalls list page shows a **Tags** column and lets you filter firewalls by tag. ## Deleting a firewall **1. Delete the firewall** Open the **Settings** tab, click **Delete**, then type the firewall name to confirm the deletion. ## Using Firewall alongside Docker Docker manages its own networking rules through iptables, which can interact unexpectedly with server-level firewalls like UFW. By default, Docker inserts its rules at a higher priority in the iptables chain than UFW, meaning incoming traffic to Docker containers bypasses UFW's restrictions entirely. This behavior ensures Docker containers can communicate but may create security gaps if not properly managed. To maintain security when using Docker with Latitude.sh Firewall, you should explicitly control container networking through Docker's own configuration: 1. Use Docker's published ports (`-p` or `--publish` flag) to specify exactly which container ports should be accessible 2. Avoid using `--network host` mode unless absolutely necessary, as it bypasses Docker's network isolation 3. Consider using Docker's built-in network policies and internal networks for container-to-container communication For detailed configuration options and best practices, refer to the Docker documentation on container networking and security. ## Firewall billing Charges apply per protected resource per month — a server or virtual machine. For the current rate, see the [pricing page](https://www.latitude.sh/network/pricing#addon). If you remove all assignments, billing stops at the end of the current billing cycle. # IP addresses Source: https://www.latitude.sh/docs/networking/ips Latitude.sh has four types of IPs: Management IPs, Additional IPs, Elastic IPs, and BYOIP. ## Types of IPs ### Management IPs When deploying a new Latitude.sh server, management IP addresses are configured by default. These IPs are used for server administration, for example, via SSH. Management IPs are permanently attached to the server, so when the instance is deleted, its management IPs go with it. ### Additional IPs You can request additional IP addresses. These can be moved between servers and belong to your account. So even if the attached instance is deleted, the Additional IP is not. When requesting Additional IPs, you are required to provide IP Justification. ### Elastic IPs Elastic IPs are portable public IPv4 /32 addresses that you create on demand, assign to a server, and move to another server within the same project. Unlike Additional IPs, which require a support request and manual approval, Elastic IPs are fully self-service. They are ideal for high availability, blue/green deployments, and flexible infrastructure setups. Learn more in the [Elastic IPs](/docs/networking/elastic-ips) documentation. ### BYOIP BYOIP (Bring Your Own IP) lets you use your own IPv4 address prefixes on Latitude.sh infrastructure. This is useful for preserving IP reputation, meeting compliance requirements, or migrating workloads without changing public-facing IP addresses. Learn more in the [BYOIP](/docs/networking/byoip) documentation. ## Requesting IP Addresses While managing a server, the need for an additional IP address might come up at some point. When that time comes, you can request additional IP addresses from your dashboard. **1. Request additional IP addresses** Select a project and click on IP addresses after logging in to your account. Click the **Request IPs** button and complete the form with the number of IPs you wish to request and the device you wish to assign them to. Justify the reason for which you need an additional IP address. This helps process the requests faster. You can find more info on IP Justification below. You will receive an email when your request is approved. When you submit your request, it will be processed by the team. All you have to do now is wait for the reply. ## IP Justification ### Why IP justification is required The number of available IPv4 addresses is nearing complete exhaustion. Just like telephone numbers, there is a limited number of possible IPv4 address combinations. Eventually, this number will run out completely. In order to ensure that available IPv4 address blocks are assigned to only those who actually require them, all additional IP requests must come with justification. Justification is not just a requirement of Latitude.sh—Latitude.sh must also justify requests made to acquire new IP blocks. IPs are not provided without justification, so this is also required of customers. ### How do I justify my IP address request? Customers requiring additional IP addresses should send a request through the dashboard by going to [latitude.sh/dashboard](https://latitude.sh/dashboard), selecting the project, clicking on the Network menu, and finally on **Request IP**. This is what is considered sufficient justification: * You must have an immediate use for at least 80% of the IP addresses that you are requesting. If you request 10 IP addresses, you should have an immediate use for at least 8 of them. The remaining 2 IPs in the request can be specified for "future use." * You should only request additional IPs for a purpose that cannot be fulfilled using IPs you already have or the server's IP address. Examples of this can include nameservers and SSL certificates. Additional IPs should not be requested for email purposes. * When justifying, you should be able to either list a valid domain name that will be assigned to each requested IP (or at least 80% of them) or, in cases where you don't immediately have a valid domain name, provide details on the specific use of each IP address. Your IP justification request will be evaluated and you will be informed if more details are required. If you have questions or concerns with the IP justification process, please contact support by opening a ticket. # Private networks Source: https://www.latitude.sh/docs/networking/private-networks Private networking allows you to group servers within the same location, enabling private communication between them Latitude.sh servers are configured with a public and a private interface on a Layer 3 network topology by default. With private networking, you can switch to a Layer 2 topology, allowing for L2 traffic between two or more instances. This applies to both bare-metal servers and the virtual machines running on them: a VM can attach to the same private network and reach the bare-metal hosts — and other VMs — over Layer 2, using the same VLAN and subnet. Layer 2 packets don't go through the network layer, and traffic is not filtered in any way. Latitude.sh does not charge for traffic from private networks, either inbound or outbound. ## Benefits & use cases Private networking provides a myriad of benefits, with the most important ones being: * Traffic doesn't go through the public internet, enhancing security. * Private network traffic doesn't count against your bandwidth quota. This feature is especially useful when you don't want or need traffic from specific servers going through the public internet. Common use cases include: * Connecting a database server to a web application privately. * Managing internal services like DHCP. * Setting up Kubernetes clusters with direct node communication. * Letting virtual machines communicate privately with the bare-metal hosts they run on. ![Create VLAN interface](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/28.Docs25Q4.CreateVLAN.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=244ae8256772fff70363fff844c38487) ## Setup ### Step 1: Create a VLAN The first step is to create a Virtual Network — commonly referred to as VLAN. **From the dashboard** **1. Create a VLAN** [Log in to the dashboard](https://www.latitude.sh/dashboard), select a project, navigate to **Networking → Private networks** in the sidebar menu, and click **Create VLAN**. Select the location and add a description to help you identify what the VLAN is used for. **Using the API** **1. Use the API** Use the [/virtual\_networks](https://www.latitude.sh/docs/api-reference/create-virtual-network) endpoint to create a VLAN. ### Step 2: Assign servers After creating the VLAN, assign at least two servers to allow the server's private IPs to communicate. ![Assign servers to VLAN](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/29.Docs25Q4.VLANassign.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=a16417aa52e598d649b95e39015f46a0) **1. Assign servers to the VLAN** Go to the Virtual Network you created and click **Assign**. Select the server you'd like to assign - only servers from the facility the virtual network was created in will be listed. Save and wait a few seconds while the network is provisioned. > [!NOTE] > > You assign **servers** to the VLAN here. Virtual machines join the same private network through the host they run on — attach a NIC to the VLAN on the host's private interface, then configure the guest as shown in **Step 3 → Virtual machines**. ### Step 3: Configure the OS The network provisioning on Latitude.sh switches is handled automatically after you assign your first server to a VLAN. Latitude.sh has no access to your servers, an additional step is required, and you need to configure the VLAN on your Operating System. **Ubuntu** **1. Load the 8021q module into the kernel and install the VLAN package** ```bash theme={null} sudo modprobe 8021q sudo apt install vlan ``` **2. Change netplan** Change the Netplan configuration file in `/etc/netplan/50-cloud-init.yaml` and add the configuration below to the end of the file. * Replace `{{VID}}` with the **VID** value from the VLAN you created. * Replace `10.8.0.1` with a private address of your choice. This address becomes the private IP of the server within the VLAN. It can be anything you want, but each server in the same VLAN needs a different IP. * Replace `eno2` with the correct interface name. For servers with bonded interfaces, use bond0. ```yaml theme={null} vlans: vlan.{{VID}}: id: {{ VID }} link: eno2 addresses: [10.8.0.1/24] ``` > [!WARNING] > > The `vlans` section should be at the same indentation level as the `ethernets` key. **3. Adding a default route** Due to eventual changes in Netplan versions, to use [Cloud Gateway](/docs/networking/cloud-gateway), you need to define a default route to ensure proper network routing. You can do that by adding the following routes section under the vlans key: ```yaml theme={null} routes: - to: 10.8.0.0/16 via: 192.168.0.1 ``` * Replace `10.8.0.0/16` with the network prefix you want to reach through eno2. * Replace `192.168.0.1` with the gateway IP address for your network (typically the first IP of your subnet). **4. Save the file and apply the configuration** ```shell theme={null} sudo netplan apply ``` This configuration is persistent, you don't need to do anything else. **Virtual machines** When the server runs virtual machines, the host's virtual bridge applies the VLAN tag for the guest. **Do not** tag the VLAN again inside the guest — a `vlans:` block in the VM double-tags the frames (QinQ), the switch drops them, ARP never resolves, and you'll see `Destination Host Unreachable`. > [!WARNING] > > Never copy the Ubuntu tag-in-guest pattern (the `vlans:` block) into a VM. On bare metal the guest tags the VLAN; on a VM the host bridge already does. Inside the guest, the private NIC must be a plain, **untagged** interface. **1. Attach a second NIC to the VM** **Latitude.sh virtual machines:** attach the VLAN with `POST /virtual_machines/{virtual_machine_id}/network_attachments`, optionally with a static `address`. A running VM restarts so the new NIC reaches the guest. After the restart, `GET /virtual_machines/{virtual_machine_id}/network_attachments` returns the NIC's `mac_address` and the `address` you set. * VMs whose `apply_network_on_boot` is `true` configure the NIC on boot when the attachment has an `address`. Nothing else to do. * In every other case (VMs created before that option existed, VMs with it set to `false`, or an attachment without an `address`), configure the NIC as described in the next steps. **Your own virtualization host:** attach a **second network interface** to the VM, connected to a VLAN-backed network whose VLAN ID matches the VLAN you created on Latitude.sh. That network's uplink must be the server's **private NIC** (`eno2`). * The VLAN ID **must match** the bare-metal VLAN's **VID**. * This is configured on the virtualization host, not in the guest OS. **2. Configure the guest NIC** Configure the private NIC as a plain, untagged interface in a configuration of your own, matched by its MAC address: interface names differ between images (`enp2s0`, `eth1`). **Do not** add a `vlans:` block. **Ubuntu and Debian (netplan):** put the private NIC in its own file, `/etc/netplan/60-private.yaml`, instead of editing `/etc/netplan/50-cloud-init.yaml`. Cloud-init can rewrite `50-cloud-init.yaml`; with your configuration in a separate file, it keeps working through any cloud-init rewrite. ```yaml theme={null} network: version: 2 ethernets: eth1: match: macaddress: "02:f2:41:f6:6a:5e" dhcp4: false addresses: [10.8.0.2/24] ``` ```shell theme={null} sudo chmod 600 /etc/netplan/60-private.yaml ``` * Replace `02:f2:41:f6:6a:5e` with the second NIC's MAC address (run `ip -br link` inside the guest to find it). * Replace `eth1` with the ID that `50-cloud-init.yaml` uses for the same MAC address, so your file overrides that entry. If `50-cloud-init.yaml` has no entry for this NIC, any ID works. * Replace `10.8.0.2/24` with a private address in the **same subnet and prefix** as the bare-metal servers on this VLAN. Each host in the VLAN needs a unique IP. * Do **not** set a gateway on this interface: keep the default route on the public NIC (`enp1s0`) only. **AlmaLinux and Rocky Linux (NetworkManager):** add a connection of your own, bound to the NIC's MAC address: ```shell theme={null} sudo nmcli connection add type ethernet con-name private ifname "*" \ 802-3-ethernet.mac-address 02:f2:41:f6:6a:5e \ ipv4.method manual ipv4.addresses 10.8.0.2/24 \ ipv4.never-default yes ipv6.method disabled ``` * Replace `02:f2:41:f6:6a:5e` and `10.8.0.2/24` as described for netplan above. * `ipv4.never-default yes` keeps the default route on the public NIC. * Until a connection of yours matches the NIC, NetworkManager may hold it with its automatic `Wired connection 1` profile (DHCP). Your connection takes over when you bring it up. > [!WARNING] > > The NIC gets a new MAC address each time the network is attached to the VM. After detaching and attaching the network again, update the MAC address and apply the configuration again: a stale MAC address leaves the NIC without its address. With netplan, update `macaddress` in your file; with NetworkManager, run `sudo nmcli connection modify private 802-3-ethernet.mac-address `. When you detach the network for good, remove your configuration first (`sudo rm /etc/netplan/60-private.yaml && sudo netplan apply`, or `sudo nmcli connection delete private`), then detach. > [!WARNING] > > Remove any leftover `vlans:` / `vlan.{{VID}}` stanza and any stray addresses on unrelated subnets before applying. Use **static** IPs on every NIC — do not run DHCP on more than one interface, or the DHCP clients race over the default route and cause intermittent packet loss. **3. Apply the configuration and verify Layer 2** ```shell netplan theme={null} sudo netplan generate sudo netplan apply ``` ```shell NetworkManager theme={null} sudo nmcli connection up private ``` With netplan, running `netplan generate` first surfaces silent errors before you apply. The address can take a few seconds to appear on the interface. Then verify Layer 2 reachability from the VM to a bare-metal host on the same VLAN. Replace `enp2s0` with the private NIC's name inside the guest (shown by `ip -br link`, next to the MAC address you used in the file): ```shell theme={null} arping -I enp2s0 sudo arp-scan --interface=enp2s0 10.8.0.0/24 ``` A reply confirms the fix. `Destination Host Unreachable` means ARP failed — the NIC is still double-tagged, or the VLAN ID, NIC, or subnet don't match the bare-metal side. **Windows** This will show you how to set up multiple VLANs on a single network interface when using Windows Server 2012 or later. ![Windows Server Private VLAN required setup.](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/1265233-ws-required-setup.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=5d1c16b8bf543f37a9d23a4ac2ea1a88) 1. If you want to configure a single VLAN in the interface, go to **Network Connections > Properties > Advanced tab > Select the VLAN ID** field and add the desired value. If you want multiple VLANs in the same interface, make sure that the property **VLAN ID is set to 0** - otherwise, it will not work. ![Setting the VLAN ID property to 0 when setting up multiple VLANs in the same interface.](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/724f944-VLANs-config-1.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=b96ed9e1ec0d5b3dff9ff1a6dc3144c6) 2. Access your server's IPMI via the [Remote access](/docs/servers/remote-access) feature. 3. On your IPMI interface go to **Server Manager > Local server** and click on **NIC Teaming**. ![NIC Teaming on your server's IPMI interface.](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/4a3f0e9-VLANs-config-02.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=67020da5f756f2431dfd287efb30b883) 4. Create a new Team with a single interface by going to **Teams > Tasks > New Team**. Select the desired interface (e.g. 40GbE) and give it a name. Once you create the Team, your IP configuration will be cleaned and your server's internet connection will be lost until the end of the process. **Select your secondary interface for the private VLAN**. ![Creating a new team with a single interface for VLAN configuration](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/92fbe55-VLANs-config-03.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=3d5471a84aafa5a66bf8f5c89a283391) 5. Go to **Adapter and Interfaces** and click on **TASKS > Add Interface**. The first interface needs to have the **VLAN ID 0 (zero)** or **Default**. ![Adding a new interface with VLAN ID 0 for default configuration](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/7b92799-VLANs-config-04.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=7d8dbe1da6a453b18b182393e55cc6ca) 6. Configure the specific VLAN and click OK. The VLAN ID that you need to configure is the same displayed on your dashboard. ![Configuring the specific VLAN ID that matches the dashboard settings](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/bb15aad-VLANs-config-05.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=107faa8fd6f69605183cdc5e4c112789) 7. To add another VLAN interface on the same port, repeat step #4. ![Adding another VLAN interface on the same port for multiple VLAN setup](https://mintcdn.com/latitudesh/ELzsuRnxGwFWx5KO/images/product/f86d34b-VLANs-config-06.png?fit=max\&auto=format\&n=ELzsuRnxGwFWx5KO\&q=85\&s=fa17f192b186511aeac446ace69a650a) 8. To assign an IP address to the new interface, click on **Network Connections**, and find the VLAN interface you have just added. Then, configure the IP similarly to any other interface. You need to configure the VLAN 0 with your public IP. You can configure any IP address in your private VLAN (e.g.: 10.10.10.1/24) and you don't need to configure a Gateway in the private interfaces. Gateway information is only mandatory for ' Public' Interfaces. ![Configuring IP address for the new VLAN interface in Network Connections](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/2e93020-VLANs-config-07.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=846c5d0f6fab466959a18c7ca098d724) Let's say you created three VLAN interfaces (VLANs 1,2,3) on the teaming interface and add three IP addresses, here is what you should see on the Server Manager window: ![Server Manager window showing three configured VLAN interfaces with assigned IP addresses](https://mintcdn.com/latitudesh/_9x7641lGNJX3WXB/images/product/660e44f-VLANs-config-08.png?fit=max\&auto=format\&n=_9x7641lGNJX3WXB\&q=85\&s=74ff64f694451004b7b5afac7a6e3d8f) **Troubleshooting** * If you try to configure multiple VLANs, make sure that the value of the VLAN ID field in the properties Advanced tab is equal to 0. * Do not configure the primary virtual interface with the VLAN ID, as it needs to be on its default configuration (VLAN ID 0). When the port configuration is set up to native VLAN, do not change this VLAN configuration. **CentOS and RedHat Enterprise Linux** **1. Load the 8021q module** In Red Hat Enterprise Linux and Centos 7, the 8021q module is loaded by default. If necessary, you can make sure that the module is loaded by issuing the following command as root: ```shell theme={null} modprobe --first-time 8021q modprobe: ERROR: could not insert '8021q': Module already in kernel ``` **2. Display module information** To display information about the module, issue the following command: ```shell theme={null} modinfo 8021q ``` **3. Additional options** See the `modprobe(8)` man page for more command options. ## Additional Resources > **Setting up 802.1Q VLAN tagging using IFCFG files** > > **1. Configure the parent interface** > > Configure the parent interface in `/etc/sysconfig/network-scripts/ifcfg-eno2`. > > ```bash theme={null} > DEVICE=eno2 > TYPE=Ethernet > BOOTPROTO=none > ONBOOT=yes > ``` > > **2. Set the VLAN interface configuration** > > Set the VLAN interface configuration in the `/etc/sysconfig/network-scripts/ directory`. The configuration file name should be the parent interface plus a `.` character followed by the VLAN ID number. For example, if the VLAN ID is 192, and the parent interface is eth0, then the configuration file name should be `ifcfg-eno2.192`: > > ```bash theme={null} > DEVICE=eno2.192 > BOOTPROTO=none > ONBOOT=yes > IPADDR=192.168.1.1 > PREFIX=24 > NETWORK=192.168.1.0 > VLAN=yes > ``` > > **3. Set up the second VLAN** > > If there is a need to configure a second VLAN, with, for example, VLAN ID 193, on the same interface, eno2, add a new file with the name `eno2.193` with the VLAN configuration details. Restart the networking service in order for the changes to take effect. As `root` issue the following command: > > ```shell theme={null} > systemctl restart network > ``` # Public networks Source: https://www.latitude.sh/docs/networking/public-networks A routed IP block scoped to a project, shared by the servers bonded onto it A **public network** is a routed block of IPs that belongs to a project, independent of any single server. It's created within a project and billed to your team. Servers on it come and go without affecting the network itself. To add a server to a public network, see [Network bonding](/docs/servers/network-bonding). > [!NOTE] > > Public networks are available for **bare metal servers** only. ## Use cases * **Shared public network:** put multiple servers on the same public network so they share one routed network — see [Network bonding](/docs/servers/network-bonding). * **Portable, server-independent IPs:** the public network and its IPs belong to the project, not to a single server. ## Public network sizes You pick a public network size at creation. The size sets how many servers the public network can hold — each public network reserves 5 IPs (2 for the network and broadcast addresses, 3 for the gateway), and the rest are usable by servers: | Size | Usable servers | | - | - | | /26 | 59 | | /27 | 27 | | /28 | 11 | | /29 | 3 | The location is fixed at creation — a public network can't be moved to another site later. ## Billing Every IP in a public network is billed **by size, from the moment you create it** — regardless of how many servers use it. See the [networking pricing page](https://www.latitude.sh/pricing/networking) for current rates. ## Creating a public network **1. Navigate to Public networks** Select a project and go to **Network → Public networks** in the sidebar. **2. Click Create public network** Click **Create public network**. Each team can have **2 public networks** by default — [contact support](https://www.latitude.sh/dashboard/support) to request an increase. **3. Choose a site and size** Select the **Site** and a **Size** (`/26`–`/29`). The size sets how many servers the public network can hold. Both are fixed once the public network is created. **4. Click Create** The public network is allocated immediately with a status of **Not bonded** — billable, but not live until you bond the first server onto it. ## Deleting a public network A public network is a separate resource from the servers on it: it survives server deletes and keeps billing until you delete it. You can only delete it once no server is bonded onto it — [tear down the bond](/docs/servers/network-bonding#removing-a-bond-teardown) on every server first, then delete the public network. Check the public network's status to confirm: it shows **Not bonded** when no server is bonded onto it, and **Bonded** otherwise. # Projects Source: https://www.latitude.sh/docs/projects Projects allow you to organize your servers and network resources, making it easier to manage your infrastructure. > [!NOTE] > > * You will receive a separate invoice for each one of your Projects. > > * Bandwidth is only pooled for servers in the same Project and country. Learn > more at [Bandwidth](/docs/usage/bandwidth). > > * Users can access all Projects in > the same Team. To limit access, [create a new Team](/docs/teams/create-team). Follow these steps to create a new project: 1. Go to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard). Click on **Create Project** in the Projects section on the dashboard home page. 2. Choose a billing option based on your needs: • **On Demand**: No long-term commitments. You'll be billed hourly or monthly. • **Reserved**: Save 65% by reserving resources for 12 months. You'll be billed annually. 3. Enter a name for your project. You can also provide a short description to help your team members understand the project's purpose. 4. Select the environment for your project from the dropdown list. If you're unsure, you can leave this field blank or set it up later. Once all the necessary information is filled out, click **Create project** to finalize the process. ## Project filtering When you select a specific project in the dashboard, all resource views will be filtered to show only resources belonging to that project. If no resources exist in the selected project, you'll see a blank state with options to create a new resource inside the current project. ![Project settings interface](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/37.Docs25Q4.ProjectSettings.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=8f7709e222d3257a9c39704b772b4386) ## Project settings The Project Settings option allows you to configure key project-specific settings, including: * Editing the project's name and description * Changing the assigned environment * Enabling bandwidth alerts * Viewing the project ID * Deleting the project **1. Access project settings** Go to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard). Select the project you want to manage using the project selector in the top navigation bar. Next to the project selector you can see the cog icon, click on it to open the project settings. ## Deleting a project > [!WARNING] > > Deleting a project is irreversible. The associated subscription will be > canceled, and any pending invoice items will be invoiced. Before proceeding, > delete all servers and other resources linked to the project. Follow these steps to delete a project: **1. Delete the project** Go to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard). Select the project you want to manage using the project selector in the top navigation bar. Next to the project selector you can see the cog icon, click on it to open the project settings. A side-panel will appear, scroll down to **Delete Project**. Click **Delete** and confirm by entering the project's name. # Referral program Source: https://www.latitude.sh/docs/referral-program The Latitude.sh **Referral Program** lets you earn rewards by sharing a unique referral link with new users. You get **\$200** in credits for each referred user who becomes a paying customer. When a new user signs up with your link, their account is linked to your referral code, and both of you receive the reward after their first payment. ## How to access your Referral Link 1. [Sign in](https://www.latitude.sh/dashboard) to your Latitude.sh account. 2. Go to **Settings** in the sidebar and select **Referral**. 3. Copy your referral link and share it however you like. ![Referral program](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/2.Docs25Q4.Referral.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=09778b8518f2abe85608e1bcdd708ceb) > [!NOTE] > > The referral code is valid for **3 months**. If no payment is made within this > time, no rewards will be given; Latitude.sh reserves the right to modify or > discontinue the Referral Program at any time. ## Reward conditions To qualify for rewards, ensure the following: • **New users only**: The referred user must be new to Latitude.sh. Existing users are **not eligible**. • **First payment requirement:** Rewards are issued immediately after the referred user's first payment. • **Qualified referrers only**: To generate a referral code and earn rewards, you must have paid at least one invoice. Latitude.sh may withhold or reverse rewards, and suspend the accounts involved, when it identifies abuse of the program, including self-referrals and coordinated accounts. # Regions & Locations Source: https://www.latitude.sh/docs/regions-locations On the [Latitude.sh dashboard](https://www.latitude.sh/dashboard) and [API](https://www.latitude.sh/docs/api-reference/summary), you'll see both **Regions** and **Locations**: • **Region**: A geographic area, usually a country, where Latitude.sh operates. Examples include the United States, Brazil, Netherlands, and the United Kingdom. • **Location**: A specific data center within a region, typically a city. If there are multiple data centers in the same city, they are labeled sequentially, e.g., **Miami** and **Miami 2**. Available locations include cities like Dallas, Miami, São Paulo, Amsterdam, and London. Go to the [Locations page](https://www.latitude.sh/locations) to view all locations available. ## Network connectivity between locations Some cities have multiple data centers that share a network infrastructure, allowing servers to communicate directly across locations. Other cities have data centers on isolated networks where cross-location communication isn't possible. ### Network sharing between city locations | Region | Locations | Network Status | Notes | | :- | :- | :- | :- | | Frankfurt | Frankfurt Frankfurt 2 | Shared network | Servers can communicate via private networking across both locations | | Sydney | Sydney Sydney 2 | Shared network | Servers can communicate via private networking across both locations | | Tokyo | Tokyo Tokyo 4 | Shared network | Servers can communicate via private networking across both locations | | Ashburn | Ashburn Ashburn 2 | Shared network | Servers can communicate via private networking across both locations | | Silicon Valley | Silicon Valley Silicon Valley 2 | Shared network | Servers can communicate via private networking across both locations | | Brazil | São Paulo São Paulo 2 | Isolated networks | Each location has its own independent network | | London | London London 2 | Isolated networks | Each location has its own independent network | | Los Angeles | Los Angeles Los Angeles 2 | Isolated networks | Each location has its own independent network | > [!NOTE] > > When creating a [private network](/docs/networking/private-networks) between > servers, you must ensure they are in the same location if the locations do not > share a network. Only servers within the same network can communicate through > private networking. ## Feature availability by location Some features are enabled per location while they roll out. The table lists the features that are currently available in a subset of locations. # Moving a server to a different project Source: https://www.latitude.sh/docs/servers/change-project You can change the project a server belongs to. This is useful in cases such as when you need to promote servers to production. Go to the page of the server you want to move and select *Switch Project* from the **Actions** button. Confirm that you'd like to move the server by typing the server hostname. ![Switch project interface](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/17.Docs25Q4.SwitchProjects.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=a7d1c6ead76ee9473b2a3bdd19074596) **Eligible destination projects** * The destination project must have the same billing option (On Demand or Reserved) as the server's current project. See [On demand vs. Reserved](/docs/billing/on-demand-vs-reserved). * Projects under a custom contract aren't available as a destination. * To move an On Demand server to a Reserved project, upgrade its billing method to yearly. See [Changing the billing method](/docs/billing/change-billing-method). **Billing** Moving a server to a different project doesn't cost anything but affects how your invoices will look for the next billing cycle. * For on-demand servers, usage counting stops for the previous project and starts for the new one. * For monthly reserved servers, you get a credit for the remaining time from the previous project and get charged for the full month for the new project. * Yearly reserved servers are not supported. Please contact the team if you need to move a project under contract. **Server status remains the same** When you move a server to a different project, no action is taken on the server itself, meaning that there is no provisioning or reimaging of your machine. # Custom disk layout Source: https://www.latitude.sh/docs/servers/custom-disk-layout Control how your server's disks are grouped, formatted, and mounted using RAID levels and custom disk layouts. If you have complex redundancy or performance requirements, you can control how your server's disks are grouped, formatted, and mounted with a **custom disk layout**. When you deploy or reinstall a server, enable **Custom disk layout** in the **Advanced** section to define exactly how disks are grouped and which RAID level each group uses. This page explains how the custom disk layout editor works and the supported RAID levels. ![Custom disk layout editor](https://mintcdn.com/latitudesh/r9o2dNUjVSTatd1E/images/product/Docs.CustomDiskLayout.png?fit=max\&auto=format\&n=r9o2dNUjVSTatd1E\&q=85\&s=92f91628fa5b4a4d6112cd173004f261) ## Availability Custom disk layouts require a server with **at least two disks** and an operating system that supports software RAID. They are not available for iPXE installs or [instant deployments](/docs/servers/instant-deployment). Use the [/plans](https://www.latitude.sh/docs/api-reference/get-plans) endpoint to check compatibility. | | RAID 0 | RAID 1 | | :- | :- | - | | Disks required | 2+ | 2+ | | Operating Systems supported | - Ubuntu 16.04 LTS or newer - CentOS 7.4 or newer - RedHat Enterprise Linux 8.4 | - Ubuntu 16.04 LTS or newer - CentOS 7.4 or newer - RedHat Enterprise Linux 8.4 | | RAID Type | Software | Software | | What it does | Combines two or more disks by striping data across them. [Read more](#raid-0) | Mirrors data between two or more disks. [Read more](#raid-1) | ## Custom disk layout Enable **Custom disk layout** to split your server's disks into up to three groups, each with its own role: | Group | Purpose | What you can set | | :- | :- | :- | | **OS** | The boot and root volume where the operating system is installed. | Number of disks, RAID level | | **Storage** | An additional data volume, formatted and mounted at a path you choose. | Number of disks, RAID level, mount point | | **Raw** | Unformatted disks left untouched for you to partition yourself after provisioning. | Number of disks | * Each group's **RAID level** can be **No RAID**, **RAID 0**, or **RAID 1**. RAID 0 and RAID 1 require at least two disks within that group. * The **Storage** group is formatted with the filesystem `ext4` and mounted at the **mount point** you choose, which defaults to `/data`. * Use **Quick apply** to fill the entire layout with a sensible default at a single RAID level (see [Default configuration](#default-configuration)). You can also configure the disk layout through the API by passing a `disk_layout` array to the [create server](https://www.latitude.sh/docs/api-reference/create-server) and reinstall endpoints. Each entry sets a `role` (`os`, `storage`, or `raw`), a disk `count`, and — where applicable — a `raid_level` and `mount_point`. For infrastructure-as-code workflows, the [Latitude.sh Terraform provider](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs) supports custom disk layouts through the `disk_layout` attribute on a `latitudesh_server` resource. Each disk group accepts the same fields as the API — a `role`, a disk `count`, and, where applicable, a `raid_level` and `mount_point`. The `disk_layout` attribute is mutually exclusive with the simpler `raid` attribute, and changing it triggers a reinstall, so the server must allow reinstalls. See the [provider documentation](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs/resources/server) for the full attribute schema. ## Default configuration When you apply a simple RAID level — either with **Quick apply** in the custom disk layout editor, or by deploying without customizing the layout — disks are grouped automatically based on how many the server has: | **# of disks** | **No RAID** | **RAID-1** | **RAID-0** | | :- | :- | :- | :- | | **1** | No raid | No raid | No raid | | **2** | No raid | RAID-1 on the two disks | RAID-0 on the two disks | | **3** | No raid | RAID-1 on the three disks | RAID-0 on the three disks | | **4 or More** | RAID-1 on smaller disks, no raid on the larger disks | RAID-1 on the two smaller disks, and RAID-1 on the larger disks | RAID-1 on the two smaller disks, and RAID-0 on the larger disks | You can fine-tune any of these defaults in the [custom disk layout](#custom-disk-layout) editor before deploying or reinstalling. ## RAID levels explained The RAID level is what determines the relationship of the disks. There are numerous RAID levels but only the ones supported by Latitude.sh are explained here. ## RAID 0 RAID 0 combines two or more disks by striping data across them, which means that chunks of data are written to each disk in the array alternately. This gives you a great performance improvement as the data is distributed between disks and each one can be utilized for both reads and writes. This approach offers great performance as you get the performance of a single disk multiplied by the number of disks in the array and also get the combined capacity of all drives, but there is one important drawback that needs to be considered. As data is being split up and divided between the disks in the array if one of the disks fails the entire array and all data is lost because the failure of a disk will remove the chunks that were written to it from the array, leaving the other disks with incomplete (as in corrupted) data. RAID 0 arrays cannot be rebuilt as there will be no knowledge by the other devices of the data that needs to be reconstructed. If you decide to run a RAID 0 array, backups are extremely important, as your entire data set depends equally on the reliability of each of the disks in the array. ## RAID 1 RAID 1 is a configuration that mirrors data between two or more disks. Everything written to the array is placed on each of the devices in the group, so each disk has a complete set of the available data. This means that you have redundancy in case of device failure. In a RAID 1 array, data is accessible as long as a single disk in the array is functioning properly. The array can be rebuilt by replacing failed drives, at which point the remaining disks will be used to copy the data back to the new device. In RAID 1 it's especially important that all disks in the array are performing well, as the performance of write operations will be that of the slowest device in the array. This happens because the whole piece of data must be written to each of the disks in the array. It's also important to note that, as all of the data lives in each disk, the total capacity of the array will be that of the smallest disk. Adding new disks increases the number of redundant copies of the data, but doesn't increase the amount of available capacity. For read operations, the theoretical performance is the same as with RAID 0 where you multiply the read speed of a single disk by the number of disks. # Custom images Source: https://www.latitude.sh/docs/servers/custom-images Custom images allow you to use iPXE scripts to boot into your operating system of choice. Using an iPXE script to deploy a custom image gives you more flexibility and control over deployments, as you can customize an operating system to your needs and requirements. You must set a valid public URL where your iPXE script is stored. Your script should follow [iPXE standards](https://ipxe.org/scripting). ## What is an iPXE script The iPXE script contains a set of instructions that specify how the network boot process should be performed. This can include loading an operating system image from a remote server, setting up network configurations, and executing custom scripts or commands. [Learn more about iPXE](https://ipxe.org/) ## DHCP Custom images use DHCP to automatically assign an IP address during boot, so you don't need to manually configure network settings. ## How to deploy a custom image 1. For the Operating System option on the server create page, paste your iPXE script under **Custom images** or select one of the examples from the right. ![Custom image selection on the Latitude.sh dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/9.Docs25Q4.CustomImages.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=41915dc9cb156b21e6d9e05e92706105) 2. Finish filling out the rest of the server create form as usual, including selecting the server type, location, and any other options you need. 3. When ready, click the **Deploy** button at the bottom of the page. Latitude.sh will begin deploying your server using your iPXE script, and you should see status updates on the server's progress in your account dashboard. Custom images take between 10 and 30 minutes to deploy, depending on the size of the image you are deploying. ## Caveats When deploying with a custom image, the server will report as active and show the **On** status in the dashboard. That doesn't mean your image has finished installing. You will need to access the server console via [Remote access](/docs/servers/remote-access) to follow the installation process and make prompt selections, if applicable. ## Alternative deployment methods If iPXE scripts don't meet your needs, you can also deploy custom operating systems using IPMI virtual media. See our [Custom OS via IPMI deployment guide](/docs/guides/ipmi-custom-os-deployment) for detailed instructions. # Deleting a server Source: https://www.latitude.sh/docs/servers/deleting-a-server Learn how to delete a server immediately or schedule it for deletion. > [!WARNING] > > Deleting a server permanently erases all data on its disks and **cannot be > undone**. Ensure you are deleting the correct server. Note that it may take up > to an hour for the deletion to reflect on your billing summary. After deletion, the server's disks are sanitized before the server is made available again. See [Disk sanitization](/docs/servers/disk-sanitization). ## Immediate deletion Follow these steps to delete a server: 1. Open the server's page on the [dashboard](https://www.latitude.sh/dashboard/). 2. Click **Actions** and select **Delete server**. 3. Confirm the deletion by typing the server's hostname. ![Delete server confirmation](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/19.Docs25Q4.DeleteServer.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=426e48b4f1545701f358b185a9c4c9ed) ## Scheduled deletion You can schedule a server for deletion at a future date, allowing you to plan decommissioning while the server continues running. To schedule a deletion: 1. Open the server's page on the [dashboard](https://www.latitude.sh/dashboard/). 2. Click **Actions** and select **Schedule deletion**. 3. Choose the date and time for the deletion. 4. Confirm by typing the server's hostname. When a server is scheduled for deletion, an alert banner appears on the server details page showing the scheduled date. ## Canceling a scheduled deletion You can cancel a scheduled deletion before it occurs. 1. Open the server's page on the [dashboard](https://www.latitude.sh/dashboard/). 2. Find the alert banner indicating the scheduled deletion. 3. Click **Cancel** on the alert banner. The server will continue running normally. # Deploying a server Source: https://www.latitude.sh/docs/servers/deploying-a-server You can deploy a bare metal server via the dashboard or [API](https://www.latitude.sh/docs/api-reference/create-server). Latitude.sh takes care of provisioning, OS installation, and configuration based on the settings you choose. Once deployment is complete, you'll receive your access credentials. ![Server deployment page](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/4.Docs25Q4.ServerDeploy.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=25aa419543784fa7fcd38da223af4982) > [!TIP] > > [metal.new](https://metal.new) takes you straight to the server deployment page. Follow these steps to deploy a server from the dashboard: **1. Access server creation** [Sign in](https://www.latitude.sh/dashboard) to your Latitude.sh account, navigate to **Bare metal** > **Servers** in the sidebar, then click **Create server**. **2. Choose hardware and operating system** Select a server based on your workload and location needs. If the configuration you need isn't available, the page may show **Join waitlist** or **Ask custom build**. Choose **Join waitlist** to get notified when stock is available, or **Ask custom build** to request a custom server setup. You can also [contact the team](https://www.latitude.sh/contact) directly. Select the Operating System. If the OS you're looking for isn't offered, you can use a [custom image](/docs/servers/custom-images) instead. > [!WARNING] > > SSH and User data are not available for some operating systems. You can list > all operating systems and their supported features using the > [/plans/operating\_systems > endpoint](https://www.latitude.sh/docs/api-reference/get-plans-operating-system). **3. Configure access and automation** Add SSH keys if desired. Password authentication is enabled by default and **disabled** when you deploy with an SSH key. This means the dashboard won't show the password to you after deployment. Learn more about creating and adding your SSH keys [here](/docs/servers/ssh-keys). > [!NOTE] > > Latitude.sh does not provide a root password when you select one or more SSH keys. Optionally, select or create a **User Data script**. User data scripts run automatically on the server's first boot through the [cloud-init](https://cloud-init.io/) process. See the [Server Configuration section](/docs/servers/user-data) for more details. Optionally, open the **Advanced** section to configure RAID or a **custom disk layout**. This is available when your server has at least two disks and you select a compatible operating system. Enable **Custom disk layout** to control how disks are grouped into OS, storage, and raw volumes — including the RAID level, filesystem, and mount point of each — or use **Quick apply** to set a simple RAID level. Use the [/plans](https://www.latitude.sh/docs/api-reference/get-plans) endpoint to check compatibility. Learn more about [custom disk layout](/docs/servers/custom-disk-layout). The **Advanced** section also has a **Bond to a public network** toggle, which joins the server's two NICs into a redundant link and places it on a routed network you own — a public network. See [Network bonding](/docs/servers/network-bonding). ![Custom disk layout editor](https://mintcdn.com/latitudesh/r9o2dNUjVSTatd1E/images/product/Docs.CustomDiskLayout.png?fit=max\&auto=format\&n=r9o2dNUjVSTatd1E\&q=85\&s=92f91628fa5b4a4d6112cd173004f261) **4. Set billing and quantity** Select the Billing Type. For **On Demand billing**, choose between hourly and monthly when deploying an instance. See the [Billing section](/docs/billing/on-demand-vs-reserved) for more information. Choose the number of servers to deploy. Select up to **5 servers** to deploy at once using the quantity selector. **5. Deploy the server** Click **Deploy** to start the provisioning process. # Disk sanitization Source: https://www.latitude.sh/docs/servers/disk-sanitization How Latitude.sh erases and verifies the disks of a server after you delete it. When you delete a server, its disks are sanitized before the server is made available to anyone else. Each disk is erased with its own built-in sanitize commands, using the strongest method it supports, and the erase is verified before the server returns to inventory. ## When sanitization runs Sanitization starts automatically after you [delete a server](/docs/servers/deleting-a-server). No action is needed from you. It runs from an isolated in-memory environment, so no disk is in use during the erase and the boot disk is included along with the data disks. ## Methods by disk type Each disk is erased with the strongest method it supports. The erase is executed by the disk itself, and disks are sanitized in parallel. ### NVMe SSD 1. **Cryptographic erase (drive sanitize).** The disk replaces its internal encryption key, so everything written under the previous key is unreadable. 2. **Block erase (drive sanitize).** The disk erases every flash block, including blocks outside the addressable space. 3. **Cryptographic erase (NVMe format).** The disk replaces its internal encryption key through the format command. 4. **User data erase (NVMe format).** The disk erases all user data. ### SATA SSD 1. **Cryptographic erase (drive sanitize).** The disk replaces its internal encryption key. 2. **Block erase (drive sanitize).** The disk erases every flash block. 3. **ATA Secure Erase.** The disk runs its own secure erase command. ### SATA HDD 1. **Cryptographic erase (drive sanitize).** The disk replaces its internal encryption key. 2. **Block erase (drive sanitize).** The disk erases every sector. ### Disks in a RAID array The array is dismantled and the RAID controller runs its sanitize command on every disk. Each disk is then verified individually. The primary methods are consistent with the Purge category of [NIST SP 800-88 Rev. 1](https://csrc.nist.gov/pubs/sp/800/88/r1/final). ## Verification Before the erase, known markers are written at fixed positions across each disk: the start, near the start, the middle, and near the end. After the erase, the disk is read back at those positions. A disk passes only when none of the markers remain. ## Sanitization report If you need a record of the sanitization for compliance, [contact support](/docs/support/contact-support) with the server ID. The report includes the date of the run, the method used on each disk, and its verification result. # Instant deployment Source: https://www.latitude.sh/docs/servers/instant-deployment Instant deployments are the fastest way to create servers on the Latitude.sh platform. Some operating systems can be deployed in less than **10 seconds**. When selecting an operating system on the server creation page, you will see a badge for operating systems that can be deployed instantly. ![Operating system selection page showing instant deployment badges on supported OS options](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/5.Docs25Q4.OSDeploy.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=72b39ea2d4982ac70d5db1a4e8cfcebd) > [!NOTE] > > This feature **does not support custom disk layouts** (including RAID) yet. > Configuring a [custom disk layout](/docs/servers/custom-disk-layout) makes the server go through > the standard deployment process, which takes approximately 10 minutes. # Logging into your server Source: https://www.latitude.sh/docs/servers/logging-into-your-server ## Access credentials When a server is deployed or reinstalled, a section on the server overview page is shown with the username and password that was set for your server. Use that, along with the public IP address, to gain access to your server for the first time. If you didn't deploy with an SSH key you'll be prompted to change your password when logging in for the first time. ![Server credentials section on the dashboard](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/6.Docs25Q4.ServerCredentials.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=99faa76a9ce94427b7e8ae96752f4c89) ## Linux The default SSH TCP port for Linux servers is 22. Root access is disabled by default so you first need to log in with the provided username and then sudo to root. To find your server credentials, go to the server overview page. You should be able to copy and paste the command to access your server. As a security measure, Latitude.sh will force you to change the password on the first login. On Windows, you can either use WSL and log in using the command from the overview page or install an application that allows you to connect via SSH. The most popular one is PuttY. ## Windows ### from Windows Windows servers are delivered with RDP and Administrator account enabled. Use the Remote Desktop Connection application. ### from Linux You will need to install a package to enable RDP sessions. Remmina is a popular one, but there are many others available. ### from Mac OS X To make a remote desktop connection, you need additional software. Commonly, the Microsoft Remote Desktop Connection Client for Mac is used, which can be found from the Mac App Store. # Instance metadata service Source: https://www.latitude.sh/docs/servers/metadata-service Access server metadata from within your bare metal servers using the instance metadata service > [!WARNING] > > The metadata service is not yet available in the **SAO** and **SAN3** regions. Support for these regions will be added in a future update. The instance metadata service provides a way for your bare metal servers to access their own metadata — such as hostname, IP addresses, network configuration, storage layout, and tags — through a local HTTP endpoint. It is available from within any running Latitude.sh bare metal server. ## How it works The metadata service runs on a link-local IP address (`169.254.169.254`) that is only reachable from within the server itself. Before querying metadata, you request a short-lived session token. You can then retrieve all metadata as a single JSON object or query individual fields by path. ## Quick start **1. Get a session token** Request a session token with a TTL (time-to-live) in seconds. The token is returned in the response body. ```bash theme={null} TOKEN=$(curl -s -X PUT "http://169.254.169.254/metadata/v1/api/token" \ -H "X-Metadata-Token-TTL-Seconds: 3600") ``` **2. Retrieve all metadata as JSON** Use the token to fetch the full metadata object: ```bash theme={null} curl -s "http://169.254.169.254/metadata/v1/metadata.json" \ -H "X-Metadata-Token: $TOKEN" | jq ``` **3. Query individual fields** You can also retrieve specific fields by path: ```bash theme={null} # Get the server hostname curl -s "http://169.254.169.254/metadata/v1/hostname" \ -H "X-Metadata-Token: $TOKEN" # Get the public IPv4 address curl -s "http://169.254.169.254/metadata/v1/public_ipv4" \ -H "X-Metadata-Token: $TOKEN" # Get the full network configuration curl -s "http://169.254.169.254/metadata/v1/network" \ -H "X-Metadata-Token: $TOKEN" | jq ``` > [!NOTE] > > The metadata service is only accessible from within the server. It cannot be reached from the public internet or from other servers. ## Available fields | Field | Description | | :- | :- | | `instance_id` | Unique server identifier | | `hostname` | Server hostname | | `local_ipv4` | Private IPv4 address | | `public_ipv4` | Public IPv4 address | | `public_ipv6` | Public IPv6 address | | `region` | Region code (e.g., `SAO`, `DAL`) | | `plan` | Server plan slug | | `operating_system` | Operating system slug | | `userdata` | User data script content | | `tags` | Tags attached to the server | | `network` | Network interfaces and DNS configuration (see [full schema](/docs/api-reference/metadata-service#response-schema)) | | `storage` | Disk information (see [full schema](/docs/api-reference/metadata-service#response-schema)) | | `ssh_keys` | SSH public keys deployed to the server | | `vendor` | Vendor-specific metadata such as project and team IDs (see [full schema](/docs/api-reference/metadata-service#response-schema)) | ## Common use cases * **Network configuration** — read interface details and IPs to configure networking at boot * **Dynamic inventory** — register the server in Ansible, Consul, or other inventory systems using its own metadata * **Cloud-init scripts** — combine with [user data](/docs/servers/user-data) to build dynamic configuration scripts that adapt to the server's environment * **Application configuration** — inject region, hostname, or tags into your application's runtime config For the complete schema, all available paths, and authentication details, see the [Instance Metadata Service API reference](/docs/api-reference/metadata-service). # Network bonding Source: https://www.latitude.sh/docs/servers/network-bonding Join a server's two NICs into one redundant link and place it on a routed network you own — a public network **Network bonding** joins a server's two NICs into one redundant `bond0` link, keeping the server connected if one link or switch port fails. A bonded server takes an IP from a public network instead of a standard public IP. Latitude.sh's OS images already include the bonding configuration, so it's applied automatically when you deploy or reinstall with bonding on. You don't configure the OS yourself. Because bonding is part of the server's configuration, reinstalling a bonded server keeps it bonded unless you explicitly turn bonding off. A bond requires a [public network](/docs/networking/public-networks). > [!WARNING] > > Bonding **replaces the server's public IP**. Update any DNS records and network automation to use the new IP before you bond a server. ## Bonding a server You bond a server when you deploy a new one, or by reinstalling an existing one. **When deploying a new server:** **1. Turn on Bond to a public network** On the **Create servers** page, find the **Bond to a public network** toggle in the **Advanced** section and turn it on. **2. Pick a public network** Choose a public network from the picker. Each option shows its CIDR, location, and how many IPs are free; a full public network is disabled. Deploy is blocked until you pick a public network. **3. Deploy** The server is delivered bonded onto the public network, with a redundant two-NIC link and an IP from the public network. **On an existing server** — reinstall it with the **Bond to a public network** toggle on. This joins the server to the public network and replaces its public IP with a bond IP. > [!NOTE] > > A bonded server's public network is **locked** — you can't re-point a bonded server to a different public network. To move a server, [tear down the bond](#removing-a-bond-teardown), then bond it onto the other public network. Not every server can be bonded: bonding has network requirements. This eligibility check applies when you reinstall an existing server: if a server doesn't meet the requirements, reinstall won't let you bond it. ## Removing a bond (teardown) **1. Turn off Bond to a public network** Open **Reinstall** for the bonded server and turn the **Bond to a public network** toggle **off**. **2. Confirm the IP change** Removing the server from its public network replaces its public IP again. Update any DNS records and network automation before you reinstall. **3. Reinstall** The bond is removed, the server's IP is freed back to the public network, and the server returns to standard networking. Teardown frees the server's IP but does **not** delete the public network or stop its billing — see [Billing](/docs/networking/public-networks#billing). ## What happens to my IP | Request | Bond state | What happens to the public IP | | - | - | - | | Deploy with bond | — | Assigned a bond IP from the public network | | Deploy without bond | — | Standard public IP; nothing bond-related happens | | Reinstall | Not bonded → bond on | Public IP **replaced** with a bond IP; server joins the public network | | Reinstall | Not bonded → bond off | No change; ordinary reinstall | | Reinstall | Bonded → bond off (teardown) | Public IP **replaced**; IP freed back to the public network; server returns to standard networking | | Reinstall | Bonded → bond on | No change; bond kept, same IP (the public network picker is locked) | | Delete server | Bonded | IP released back to the public network; the public network stays and keeps billing | ## FAQ **Why does deleting my server still bill me?** The public network is billed separately from the server. See [Billing](/docs/networking/public-networks#billing). **Why can't I delete my public network?** A server is still bonded onto it. See [Deleting a public network](/docs/networking/public-networks#deleting-a-public-network). **Can I move a server to another public network?** No — a bonded server's public network is locked. Tear down the bond, then bond the server onto the other public network. # Operating systems Source: https://www.latitude.sh/docs/servers/operating-systems Latitude.sh provides a variety of Operating systems that you can use to create your servers, such as Windows and Linux distributions. You can find all supported operating systems by going to the [server create page](https://metal.new) or through the following API request. ```shell theme={null} curl --request GET \ --url https://api.latitude.sh/plans/operating_systems \ --header 'Authorization: Bearer ' ``` ## ML-in-a-Box ML-in-a-Box is a custom image built by Latitude.sh that you can use to get started quickly with any of the GPU servers available. This image comes with several dependencies needed for Machine Learning and AI workloads and is automatically selected when you are deploying a GPU server and select Ubuntu as the Operating System. The versions of the installed dependencies are optimized for compatibility and might not be the latest versions available. | Depdendency | Version | | :- | :- | | Python | 3.10 | | NVIDIA CUDA | 13.0 | | NVIDIA Driver | 580.105.08 | | NVIDIA Container Toolkit | 1.18.0-1 | | Docker | 29.0.0 | | PyTorch | 2.9.0+cu130 | ## Custom images Installing your own images is supported through iPXE scripts. Go to [Custom image (iPXE)](/docs/servers/custom-images) to learn more. # Out-of-band Source: https://www.latitude.sh/docs/servers/out-of-band Out-of-Band (OOB) gives you direct access to your server’s hardware-level serial console over SSH. This lets you see and interact with the system before and during boot, including BIOS, GRUB, and early kernel output. Out-of-band automatically enables a serial login on the server after boot, so you can also use OOB to administer Linux even when normal SSH is unavailable. ### What to expect A Serial-over-LAN console behaves differently from a normal SSH session: * It is lower bandwidth and may refresh slowly * The BIOS interface appears in text mode * Keystrokes may feel slightly delayed * It looks like a normal terminal after login, but it is still a serial console * Graphical KVM output is not available here (use [Remote Access](/docs/servers/remote-access) instead) Despite these limitations, OOB provides full control of the machine at every boot stage. For full graphical keyboard-video-mouse access, use Remote Access. ## Requirements To access your server’s serial console you need: * An SSH key (configured in your Latitude.sh account) to open the OOB connection * An OS user password set on the server — required to log in to Linux through the serial console > [!WARNING] > > Servers deployed with only an SSH key don’t have an OS password by default. Before relying on OOB to log in after boot, SSH into the server and set one — run `passwd` to set the root password, or `sudo passwd ` for another OS user. If you lost your root password, use [Rescue mode](/docs/servers/rescue-mode) to reset it. ## Creating an OOB connection [Use Out-of-Band on your Latitude.sh Metal server](https://demo.arcade.software/xugkQX7Ikt69atSJCww8?embed\&embed_mobile=tab\&embed_desktop=inline\&squared=true\&show_copy_link=true) 1. Go to the server page, click the **Recovery** tab, and select **Out-of-Band**. 2. Select your SSH key and click **Enable out-of-band**. 3. Wait until the process finishes and the status change from **Connecting** to **Connected**. ## Using the console Copy the command snippet from the side panel on your terminal. It will look similar to this: ```shell theme={null} ssh @ -p 2222 ``` If OOB is active, you will see: ```shell theme={null} [SOL Session operational. Use ~? for help] ``` ### Capabilities #### Before boot You can: * Change boot order * Inspect hardware setup When you reboot you can: * Enter BIOS (DEL/ESC) * View POST and GRUB #### After boot Hit Enter to see the Linux login prompt: ![A login prompt when using OOB.](https://mintcdn.com/latitudesh/GM0FinvY4oaPgX2y/images/product/52.Docs25Q4.Outofband.png?fit=max\&auto=format\&n=GM0FinvY4oaPgX2y\&q=85\&s=8c25644cc50db933fb7ee5803684f489) Log in with the OS user password you set on the server (`root` or another user with a password). This gives you a full Linux shell, identical in function to SSH but running on the serial console (ttyS0) instead of a network connection. ## Ending the session To close the OOB session: ```shell theme={null} ~. ``` (tilde, then dot) # Power management Source: https://www.latitude.sh/docs/servers/power-management To power cycle your server, go to the server's overview page and click on the Power Cycle dropdown. Choose one of the available options. ![Power cycling a server from the Latitude.sh dashboard.](https://mintcdn.com/latitudesh/FBYR_HM74E1bL9HH/images/product/18.Docs25Q4.PowerMgmt.png?fit=max\&auto=format\&n=FBYR_HM74E1bL9HH\&q=85\&s=fc948ec20c25dcaa098c9a300bf790d9) On shutdown and reboot operations, the platform tries to gracefully shut down the machine before booting it again. If the graceful shutdown operation fails, a subsequent request is sent to forcefully shut it down. If you prefer to manage this yourself, use the [power cycle endpoint](https://www.latitude.sh/docs/api-reference/create-server-action). > [!NOTE] > > Shutting down a server does not pause billing. To avoid charges, you have to delete the server > instead. # Reinstalling a server Source: https://www.latitude.sh/docs/servers/reinstalling-a-server > [!WARNING] > > Reinstalling a server completely erases all disks on it and creates a fresh > install of the OS of your choice. This process is irreversible, so please use > caution. To reinstall a server, go to the server page, click on the **Actions** button and select **Reinstall**. You will be presented with the available options to reinstall the device. ![Reinstall server options](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/16.Docs25Q4.ReinstallServer.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=089f0749349f2d671df0e4727d972aa2) Alongside the operating system, SSH keys, and user data, you can adjust the **disk layout** when your server and operating system support it. Enable **Custom disk layout** to change how disks are grouped, formatted, and mounted. See [custom disk layout](/docs/servers/custom-disk-layout) for details. Reinstalling is also how you bond an existing server onto a public network, or remove an existing bond — toggle **Bond to a public network** in the reinstall options. Bonding or unbonding replaces the server's public IP. See [Network bonding](/docs/servers/network-bonding). When submitting a reinstall request, the system formats the disks and installs the selected operating system. You can follow the reinstall progress of your server. # Remote access Source: https://www.latitude.sh/docs/servers/remote-access All of Latitude.sh's servers feature remote access capabilities so your server can be managed even when it's off or unresponsive. You can choose between two remote access methods: **Direct IPMI Access** (recommended) and **VPN Access**. Remote Access is included at no cost. ## Selecting Your Remote Access Method When you first access the Remote Access feature for a server, you'll be presented with a method selection interface that defaults to the recommended Direct IPMI Access method: 1. Navigate to your server's overview page 2. Click on the **Remote Access** action 3. Choose your preferred method from the dropdown: * **Direct IPMI Access** (Recommended): Direct browser-based IPMI access - easier method but doesn't support the JAVA console * **VPN Access**: Connect through a secure VPN session to access IPMI - supports the JAVA console if needed Your selected method will be automatically saved and remembered for each server. You can change methods at any time using the dropdown selector at the top of the Remote Access interface. ## Direct IPMI Access (Recommended) Direct IPMI Access provides immediate browser-based access to your server's Intelligent Platform Management Interface (IPMI). This is the recommended method for remote server management as it provides an easier method to access and manage your server, but doesn't support the JAVA console. ![Remote access interface](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/13.Docs25Q4.RemoteAccess.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=133402850935d991439c7f9e7c2ff8db) ### Connecting to Direct IPMI 1. Select **Direct IPMI Access** from the method dropdown (this is the default selection) 2. Click **Generate IPMI credentials** to create access credentials 3. Copy the username and password provided 4. Click **Access IPMI** to open the IPMI interface in your browser 5. Log in using the generated credentials > [!WARNING] > > The IPMI password is only shown once, so you'll need to generate new > credentials if you need to access your server again in the future. ## VPN Access VPN Access provides a secure connection to your server's IPMI through a dedicated VPN session. If you need to use the JAVA console feature, use VPN Access instead of Direct IPMI Access. ### Setting up VPN Access 1. Select **VPN Access** from the method dropdown 2. Click **Create VPN session** to establish a new VPN connection 3. Once created, you'll see the VPN connection details including: * **Host**: VPN server address * **Port**: Connection port * **Username**: Your VPN username * **Password**: Your VPN password (can be refreshed if needed) * **Expires at**: Session expiration time ### Connecting via VPN 1. **Step 1: Connect to the VPN** using the provided credentials with your preferred VPN client 2. **Step 2: Access IPMI** once connected to the VPN, you'll be able to access your server's IPMI interface ### Managing VPN Sessions * **Refresh Password**: Click the refresh button next to the password field to generate a new password * **Delete Session**: Click **Delete VPN session** to terminate the current VPN connection * VPN sessions automatically expire after the specified time period ## Troubleshooting ### General Issues * The remote access feature only supports HTML5 console * If you need to deploy a custom image, use the iPXE option available on the dashboard * Your method preference is saved per server, so you can use different methods for different servers ### Direct IPMI Issues * The IPMI URL may take a few seconds to become available after generation * Make sure to copy credentials before closing the interface, as they're only shown once ### VPN Access Issues * Ensure your VPN client supports the connection type provided * Check that the VPN session hasn't expired * Try refreshing the VPN password if you're having authentication issues If you encounter any issues with either access method, please contact support. # Rescue mode Source: https://www.latitude.sh/docs/servers/rescue-mode Rescue mode is useful when you lose access to your server and SSH becomes unreachable. It allows you to recover data and make changes to the instance without having to use [Remote access](/docs/servers/remote-access) or reinstall the device. When you put a server in rescue mode, a lightweight Ubuntu image is loaded into your server's memory. This allows you to SSH to the machine and do maintenance. > [!WARNING] > > Rescue is not available for servers running Windows. > [!NOTE] > > Rescue mode is not available at certain locations. If you don't see this option in the **Actions** menu, it's not supported at your server's location. ## Booting into Rescue Mode In order to boot into rescue mode, simply go the server page, click **Actions** and select *Rescue mode*. ![Rescue mode activation](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/14.Docs25Q4.RescueMode1.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=be8a23da7be8c651aa58b8bde639ae06) ### Accessing the server When the server finishes loading the rescue operating system, a user and password with root access will be shown on the server page. ![Rescue mode credentials](https://mintcdn.com/latitudesh/jTa6J8Hv5F4W4vnJ/images/product/15.Docs25Q4.RescueMode2.png?fit=max\&auto=format\&n=jTa6J8Hv5F4W4vnJ\&q=85\&s=dbb637bdb7a1f9bee9efe98f84d5c9f4) ### Mounting the root partition The first thing to do is find the root partition. Running `lsblk` will retrieve all partitions. Find the disk that represents the root partition of your server. This is usually the largest partition from the ones listed. Mount the partition replacing the placeholder with the root partition name: ```shell theme={null} sudo mount /dev/sda2 /mnt -t ext4 ``` Here the root partition `/dev/sda2` is being mounted to the `/mnt` dir. Root partition for servers with NVMe disks are slightly different, similar to the example below: ```shell theme={null} sudo mount /dev/nvme0n1p1 /mnt -t ext4 ``` When the partition mounts successfully, go to the `/mnt` directory to work on your files. ```shell theme={null} cd /mnt ``` ## Troubleshooting If issues are found entering or exiting rescue mode, the server will return to its previous state, either Deployed or Failed, depending on the case. This is an indication to use [Remote access](/docs/servers/remote-access) to troubleshoot your server instead. # SSH keys Source: https://www.latitude.sh/docs/servers/ssh-keys Latitude.sh allows you to deploy servers using SSH keys. SSH is extremely easy to get started and provides a secure way of logging into your servers. Here you can learn what SSH is, how it works, and how to create SSH keys on Windows, Linux, and macOS. If you're already comfortable with SSH, head to [Adding your SSH key](#adding-your-ssh-key) . ## What is SSH SSH is a remote administration protocol that allows users to control and modify their servers remotely. SSH uses cryptographic techniques to ensure that all communication to and from the remote server happens in an encrypted manner. It provides a mechanism for authenticating a user, transferring inputs from the client to the host, and relaying the output back to the client. Any Linux or Mac user can SSH into their remote server directly from the terminal window. ### How does SSH work Linux or Mac enables you to use SSH clients straight from the terminal window. If you use Windows, you will need to download an SSH client to open SSH connections. The most popular SSH client is [PuTTY](https://www.putty.org/). The SSH command consists of three distinct parts: ```shell theme={null} ssh {user}@{host} ``` The SSH key command instructs your system that you want to open an encrypted Secure Shell Connection. `{user}` represents the account you want to access. For example, you may want to access the root user, which is basically synonymous for system administrator with complete rights to modify anything on the system. `{host}` refers to the computer you want to access. This can be an IP Address or a domain name (e.g. `http://www.xyzdomain.com`). When you hit enter, you will be prompted to enter the password for the requested account. When you type it in, nothing will appear on the screen, but your password is, in fact being transmitted. Once you're done typing, hit enter once again. If your password is correct, you will be greeted with a remote terminal window. You can read more about SSH commands [here](https://www.ssh.com/academy/ssh/command). ### On Windows You can create SSH keys in many ways. Windows requires an SSH client but doesn't have a default SSH client on their operating system. The easiest way is to generate SSH Keys using [PuttY](https://www.putty.org/). **1. Download and set up PuTTY** Download PuTTY. The two binaries you will need are: * PuTTY (the SSH and Telnet client itself) * PuTTYgen (an RSA and DSA key generation utility) Open the PuTTYgen program and for the Type of key to generate, select SSH-2 RSA. Click the Generate button. **2. Configure and save keys** Type a passphrase in the **Key passphrase** field. Type the same passphrase in the **Confirm passphrase** field. You can use a key without a passphrase, but this is not recommended. Click the **Save private key** button to save the private key. Important: Never share your private key with anyone. Copy the contents under **Public key** for pasting into OpenSSH **authorized\_keys** file. Save the contents you just copied somewhere. This is the public key you're going to use with Latitude.sh and any other services you'd like to connect with SSH. You can save it as a .txt file in order to be able to open it with a text file later. ### On Linux & macOS When you generate the keys, you will use `ssh-keygen` to store the keys in a safe location so you can bypass the login prompt when connecting to your instances. **1. Generate SSH key pair** Open a Terminal window and enter the following command: `ssh-keygen -t rsa`. This starts the key generation process. When you execute this command, the `ssh-keygen` utility prompts you to indicate where to store the key. Press the **ENTER** key to accept the default location. The `ssh-keygen` utility prompts you for a passphrase. Type in a passphrase. You can also hit the ENTER key to accept the default (no passphrase). However, this is not recommended. You will need to enter the passphrase a second time to continue. After you confirm the passphrase, the system generates the key pair. Example terminal response ```shell theme={null} Your identification has been saved in /Users/myname/.ssh/id_rsa. Your public key has been saved in /Users/myname/.ssh/id_rsa.pub. The key fingerprint is: ae:89:72:0b:85:da:5a:f4:7c:1f:c2:43:fd:c6:44:38 user@my-name.local The key's randomart image is: +--[ RSA 2048]----+ | | | . | | E . | | . . o | | o . . S . | | + + o . + | |. + o = o + | | o...o * o | |. oo.o . | +-----------------+ ``` Your private key is saved to the `id_rsa` file in the `.ssh` directory. **Never share your private key with anyone.** Your public key is saved to the `id_rsa.pub` file and is the key you upload to your Latitude.sh account. You can save this key to the clipboard by running this: ```shell theme={null} pbcopy < ~/.ssh/id_rsa.pub ``` Now continue to SSH Key Access to learn how to import your recently generated SSH key to Latitude.sh. ## Adding your SSH Key If you already have an SSH key pair, you can use it to import it into Latitude.sh. ![SSH keys management page](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/7.Docs25Q4.SSHkeys.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=36e10643988239d9af154067f84f6d0f) **1. Add your SSH key to Latitude.sh** Go to the [Latitude.sh dashboard](https://www.latitude.sh/dashboard), select a project, and navigate to **Compute > SSH keys** in the sidebar. Click on **Add SSH Key**, paste your Public SSH Key, and choose a name for it. The name is only used to help you easily identify the key afterward. It's recommended you use your e-mail as part of the key name as all users of your team will have access to the imported keys. Click **Add** and the key will be ready to use when deploying or reinstalling a server. There's no limit to the number of keys you can add and use with your servers. ## Project and Team scope When you create an SSH key, you can choose whether to make it available across all projects in your team or scope it to a specific project. ![SSH keys scope on creation](https://mintcdn.com/latitudesh/h9AEAyEtiVGR6o52/images/product/SSHkeys.Scope.png?fit=max\&auto=format\&n=h9AEAyEtiVGR6o52\&q=85\&s=d424dd8474b5c20065187e6c31c90e71) * **Team**: Available across all projects in your team. This is the default scope. * **Project**: Only available within the current project. The SSH keys page shows these as two separate tabs. When selecting SSH keys during deployment or reinstallation, your keys will be grouped by scope, with project-scoped keys appearing first, then team-scoped keys. ![SSH keys selector](https://mintcdn.com/latitudesh/h9AEAyEtiVGR6o52/images/product/SSHkeys.Selector.png?fit=max\&auto=format\&n=h9AEAyEtiVGR6o52\&q=85\&s=b5f85552348c862c3d4afb2f6ac3edde) ## Using your SSH key When deploying or reinstalling servers, you can select from your existing SSH keys or create new ones. You can use as many keys as you want for each server. If you need to add a new SSH key during deployment or reinstallation, you can create it directly in the workflow. When creating a key, choose whether it should be scoped to the current project or available across all projects in your team. When you deploy with an SSH key, Latitude.sh *does not* disable password login. # User data Source: https://www.latitude.sh/docs/servers/user-data User data are scripts that use the `cloud-config` format, designed to be run by the cloud-init process. These scripts are generally used for the initial configuration of a server and run on the first boot. Deploying a server with user data allows you to run arbitrary commands and change several aspects of the server during provisioning. Here are a few examples of what you can do with user data scripts: * Change user passwords * Server hardening * Notify people or systems that a new device has been deployed * Install packages and dependencies ![User data management page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.Create.Template.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=1b5c3118783c1474642ae75b20c7c374) ## Compatibility Here are the operating systems that currently support setting user data and the directive you should use when writing your scripts. | Distro | OS | Directive | Language | | :- | :- | :- | :- | | Linux | - Ubuntu 16.04 LTS and newer - CentOS 7.4 and newer - Rocky Linux - Debian 10 and newer - RedHat Enterprise Linux | `#cloud-config` | YAML | | Windows | - All Windows images | `# ps1_sysnative` | PowerShell | ## File format ### UNIX-like systems If you're using a UNIX-like OS like Linux, your scripts must be written using the YAML file format, which uses whitespace and new lines to delimit lists, associative arrays, and values. Here's an example of a user data script that uses the `{{ PASSWORD }}` variable to change the root password and allow for root logins. ```yaml theme={null} #cloud-config user: root chpasswd: { expire: false } password: { { PASSWORD } } disable_root: false ssh_pwauth: true runcmd: - echo "PermitRootLogin yes" >> /etc/ssh/sshd_config - systemctl restart ssh ``` These files are generally fairly intuitive and easy to understand, but there are a few things you need to keep in mind when using them. Here is a good [getting started guide](https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html) that can help. > [!NOTE] > > Always validate your YAML code. Google 'YAML validator' if you don't have a > linter on your IDE, but remember never to add sensitive data to these > services. ### Windows systems For Windows, you'll have to use the `cloud-baseinit` convention. This is just a fancy way of saying that your user data will have to be written as if you were using Powershell. Here's a straightforward example: ```powershell theme={null} #ps1_sysnative mkdir c:/test New-Item c:/test/test.txt Set-Content c:/test/test.txt 'Hello World' ``` ## Creating a user data Before creating a user data script, make sure you're using the [correct directive and programming language](#compatibility) for the operating system you'll be using it with. ### From scratch **1. Create user data from scratch** Go to the [dashboard](https://www.latitude.sh/dashboard), select a project, and navigate to **Compute > User data** in the sidebar. Click **Create user data...** and choose **From scratch**. ![User data creation page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.Create.Select.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=6de1b4863a0501e7cb71ba1231a3383f) **2. Choose scope** Select whether to make this user data available across all projects (**Team**) or only within the current project (**Project**). ![User data creation page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.Create.Scope.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=2c8673beb2aa9710b846817c2960cb91) **3. Add content** Write your user data script using the [correct directive and language](#compatibility) for your operating system. ### From a template You can start with user data scripts by choosing one of the provided templates. From package updates to notifying Slack on deploys, templates are available for different use cases. **1. Create user data from template** Go to the [dashboard](https://www.latitude.sh/dashboard), select a project, and navigate to **Compute > User data** in the sidebar, click **Create user data...** and choose **From template**. ![User data creation page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.Create.Select.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=6de1b4863a0501e7cb71ba1231a3383f) **2. Select template and scope** Choose the template you want to use. Select whether to make this user data available to all projects (**Team**) or only the current project (**Project**). ![User data creation page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.Create.Template.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=1b5c3118783c1474642ae75b20c7c374) **3. Customize and save** Click **Use this template**, then edit the content as needed. ## Project and Team scope When you create a user data script, you can choose whether to make it available across all projects in your team or scope it to a specific project. * **Team**: Available across all projects in your team. This is the default scope. * **Project**: Only available within the current project. Useful for project-specific server configuration. The user data page shows two tabs for managing these scopes. ![User data management page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.List.Tabs.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=82efb668c9697db0cbd0fc177d75a6db) When selecting user data during deployment or reinstallation, your scripts will be grouped by scope, with project-scoped scripts appearing first, then team-scoped scripts. ![User data management page](https://mintcdn.com/latitudesh/2hRUs1WyztyTmUj8/images/product/UserData.List.Select.png?fit=max\&auto=format\&n=2hRUs1WyztyTmUj8\&q=85\&s=978fbdec9131a9e3ee712d6b81bf6b11) ## Variables To make development easier, variables are provided that can be used in your user data script so you can access data that is only available during or right after a deployment. Variables are wrapped in double curly brackets (`{{ VAR }}`). Here are the available variables that can be used by any user data script. | Variable | Value | | :- | :- | | `{{ HOSTNAME }}` | The normalized hostname. | | `{{ PASSWORD }}` | Root password of the deployed server. | | `{{ USER_DISTRO }}` | Distro username. Examples: ubuntu, centos, Admin. | | `{{ MAC_ADDRESS }}` | MAC Address. | | `{{ PUBLIC_IPV4 }}` | Public IPv4 address. | | `{{ SSH_KEYS }}` | An array of the SSH keys you chose to deploy your server with, if any. | | `{{ SERIAL }}` | Windows serial (only available for Windows systems). | ## Examples * [Examples repository](https://github.com/latitudesh/examples) * [cloud-init's docs](https://cloudinit.readthedocs.io/en/latest/topics/examples.html). # Service Schedules Source: https://www.latitude.sh/docs/sla # Block storage Source: https://www.latitude.sh/docs/storage/block-storage High performance block volumes you map to a bare metal server and use over NVMe/TCP Block storage gives you persistent, high performance volumes for bare metal servers. A volume lives independently of any server: you create it in a project, map it to one of your servers, and the server reaches it over a private storage network using NVMe/TCP. Data stays on the volume when you unmap it, so you can move it to another server in the same location. ## Prerequisites * A verified team and a project in a location where high performance storage is available. The create flow only lists those locations. * A bare metal server in the same project and location as the volume, bonded onto a [public network](/docs/networking/public-networks). Bonding gives the server the redundant `bond0` link the storage network is delivered on. See [Network bonding](/docs/servers/network-bonding). * One of the [supported operating systems](#supported-operating-systems) if you want the server to be configured automatically. ## Creating a volume **1. Open the create flow** In the dashboard, go to **Storage** > **Block storage** and click **Create volume**. **2. Choose a location and size** Pick the location and set the capacity, from 32 GB to 30 TB. The volume must be in the same location as the server you plan to map it to. **3. Create** Click **Create volume**. The volume opens on its detail page, ready to be mapped. ## Mapping a volume to a server Mapping connects the volume to one server. The server must be in the volume's project and location. **1. Pick a server** On the volume page, open the server picker under **Assigned server**. Servers already on a public network show a **Bonded** badge and can be selected. Servers that support bonding but aren't on a public network yet show **Reinstall to bond** and can't be selected until you [bond them](/docs/servers/network-bonding). Servers that can't be bonded aren't listed. **2. Assign** Click **Assign**. The status shows **Mapping** while the volume is being attached, then **Mapped**. If the mapping fails, pick a server and try again. > [!NOTE] > > If the volume's location has no public network in your project yet, the volume page offers to create one before you can pick a server. ## Activating storage networking on the server Once the volume is mapped, the server needs a storage VLAN on top of its bond and an NVMe/TCP connection to the volume. You can let Latitude.sh configure this, or do it yourself. Both options appear on the volume page after you [map the volume to a server](#mapping-a-volume-to-a-server), once its status shows **Mapped**. ### Option 1: Reinstall Click **Reinstall** on the volume page. Reinstalling with a [supported operating system](#supported-operating-systems) configures the storage VLAN, the routes and the NVMe/TCP connection automatically, and connects the volume on boot. > [!WARNING] > > Reinstalling erases the server's disks. Back up anything you need first. ### Option 2: Configure manually If you don't want to reinstall, click **View guide** on the volume page. The guide lists the commands for your server and fills in the values the platform already knows, such as the storage VLAN id. Anything still shown as a placeholder, such as the storage IP or gateway, comes from Latitude support; replace it before applying. In short: **1. Add the storage VLAN on top of the bond** Create a netplan file that defines a VLAN on `bond0` with the storage IP and the routes to the storage networks, then apply it with `sudo netplan generate` and `sudo netplan apply`. **2. Run the storage setup script** Download and run `lsh-block-setup.sh`. It installs the NVMe/TCP tooling, sets the server's NVMe host name, and seeds the discovery target. Review the script before running it; it lists its changes and only acts with your approval. **3. Connect the volume** Run `sudo nvme connect-all`. The volume appears as an NVMe device on the server. > [!WARNING] > > The manual path changes live networking on the server. Keep an out-of-band session open as a fallback. ## Using the volume After connecting, the volume shows up as a new NVMe device. Device numbers such as `nvme1n1` change between servers and can point at a local disk, so identify the volume before touching it: ```bash theme={null} sudo nvme list lsblk -o NAME,SIZE,MODEL,SERIAL,MOUNTPOINTS ``` The mapped volume is the NVMe/TCP device whose size matches the volume you created. Format and mount it using its stable path under `/dev/disk/by-id/`, and keep that path for `/etc/fstab` so a device renumbering after reboot can't mount the wrong disk: ```bash theme={null} VOLUME=/dev/disk/by-id/nvme-example-model_example-serial ls -l "$VOLUME" sudo mkfs.ext4 "$VOLUME" sudo mkdir -p /mnt/volume sudo mount "$VOLUME" /mnt/volume ``` Set `VOLUME` to the entry under `/dev/disk/by-id/` that matches the serial you found. The `ls` line confirms it points at the device you expect. > [!WARNING] > > Formatting erases the device. Double-check the size and serial before running `mkfs`. ## Performance Measured with `fio` and direct I/O on the unformatted volume, from a server with a 2×10 Gbps bond: | Workload | Result | | - | - | | Sequential read, 1 MiB | 2.3 GB/s | | Sequential write, 1 MiB | 2.1 GB/s | | Random read, 4 KiB | 460K IOPS | | Random write, 4 KiB | 100K IOPS | Results depend on the server's network capacity, the filesystem and the workload. Traffic to the volume uses both links of the bond with no tuning. At these rates, sequential throughput and random reads are limited by the server's network. These results use many parallel requests. The random read result needs about 1,000 requests in flight, for example 16 threads at a queue depth of 64. A single 4 KiB request takes about 0.4 ms to read and 0.9 ms to write, similar to [file storage](/docs/storage/filesystem#performance). ## Expanding a volume Volumes can grow but not shrink. Use **Expand** in the volume's actions menu and pick a new size, up to 30 TB. Volumes can be expanded while mapped, and the server keeps running. Billing is prorated to the new size from the day you expand. If **Expand** doesn't appear for a volume, that volume can't be resized; contact support. After the resize, set `VOLUME` to the volume's path under `/dev/disk/by-id/`, as in [Using the volume](#using-the-volume), and confirm the server sees the new size: ```bash theme={null} VOLUME=/dev/disk/by-id/nvme-example-model_example-serial lsblk -o NAME,SIZE "$VOLUME" ``` If it still shows the old size, list the volume's NVMe/TCP controllers: ```bash theme={null} sudo nvme list-subsys "$(readlink -f "$VOLUME")" ``` Each line starting with `+-` names one of the volume's controllers, such as `nvme10`. Rescan any of them, replacing `` with its name: ```bash theme={null} sudo nvme ns-rescan /dev/ ``` Then grow the filesystem to use the new space. For ext4, this works while the volume is mounted: ```bash theme={null} sudo resize2fs "$VOLUME" ``` For XFS, run `sudo xfs_growfs /mnt/volume` instead. ## Unmapping and deleting To move a volume to another server, release it on the server first: stop anything using the mount, unmount it, and remove its `/etc/fstab` entry so the next boot doesn't wait for a device that is no longer there. ```bash theme={null} sudo umount /mnt/volume ``` Then click **Unmap server** on the volume page. The status shows **Unmapping** until the volume is detached. Data on the volume is preserved and you can map it to another server in the same location. To delete a volume, unmap it and use **Delete volume** in the volume's actions menu. Deleting a volume permanently removes its data. ## Supported operating systems Automatic configuration on reinstall is available for these images: * Debian 13 * Ubuntu 24.04 and 26.04 * AlmaLinux 9 and 10 * Rocky Linux 9 and 10 On other operating systems, use the manual guide. ## Current limits * Map one block volume per server for now. * A volume can be up to 30 TB. * Volumes can be expanded but not shrunk. Create a new volume if you need a smaller one. * A volume can only be mapped to a server in the same project and location. * Automatic configuration requires a reinstall with a supported operating system. On other images or without a reinstall, follow the manual guide. These limits are being worked on and will be lifted in upcoming releases. ## Pricing Block storage costs \$0.08 per GB per month, billed on provisioned capacity while the volume exists, whether or not it is mapped. The total for the size you choose is shown in the create flow before you confirm. See the [storage pricing page](https://www.latitude.sh/pricing/storage) for details. # Egress Source: https://www.latitude.sh/docs/storage/egress Traffic to and from your Latitude.sh storage is free Latitude.sh storage products do not charge egress fees. Traffic to and from your storage is free, in either direction, regardless of the storage product. The network path differs by product, because Object storage and Block / File storage are reached differently: * **Object storage** is reached over the public internet through its S3 endpoint. * **Block and File storage** attach over the storage network. ## Summary | Direction | Billed? | | :- | :- | | Object storage ↔ internet | Free | | Object storage ↔ your server | Free | | Block storage ↔ your server | Free | | File storage ↔ your server | Free | ## Object storage Object storage is reached over the public internet through its [S3 endpoint](/docs/storage/object-storage#connection-details). Traffic between your Latitude.sh server and the bucket leaves the server through its public network interface, just like any other internet request. * **Traffic out of a bucket is free**, no matter where it goes. Reads to your Latitude.sh server, to an application on your laptop, or to another cloud are not billed by Latitude.sh. * **Traffic into a bucket is free**, whether it comes from the internet or from your Latitude.sh server. If you connect from outside Latitude.sh (for example, from a laptop or another provider), Latitude.sh does not charge for the traffic on its side. Your local ISP or cloud provider may have its own egress fees. ## Block storage Block volumes attach to bare metal servers over Latitude.sh's storage network using a block protocol. They never touch the public internet. * **All traffic between your server and the volume is free**, in either direction. ## File storage File systems attach to bare metal servers over Latitude.sh's storage network using a file protocol. They never touch the public internet. * **All traffic between your server and the file system is free**, in either direction. ## Frequently asked questions > **Is uploading to a bucket billed as a storage fee?** > > No. Latitude.sh Object storage does not charge for egress. Uploads to a > bucket are free. > **Does this change if I'm uploading from outside Latitude.sh?** > > No. Uploads to a bucket from a laptop, another cloud, or any > non-Latitude.sh source are free on the Latitude.sh side. Your origin's own > provider may have its own egress fees. # File storage Source: https://www.latitude.sh/docs/storage/filesystem Shared NFS filesystems you mount on bare metal servers over the private storage network File storage gives you persistent filesystems that several servers can mount at the same time. A filesystem lives independently of any server: you create it in a project, and servers in the same project and location mount it over NFS through a private storage network. Data stays on the filesystem when servers are reinstalled or removed. ## Prerequisites * A verified team with a payment method or credit balance, and a project in a location where file storage is available. The create flow only lists those locations. * A bare metal server in the same project and location as the filesystem, bonded onto a [public network](/docs/networking/public-networks). Bonding gives the server the redundant `bond0` link the storage network is delivered on. See [Network bonding](/docs/servers/network-bonding). * One of the [supported operating systems](#supported-operating-systems) if you want the server to be configured automatically. ## Creating a filesystem **1. Open the create flow** In the dashboard, go to **Storage** > **File storage** and click **Create filesystem**. **2. Choose a location** Pick the location. The filesystem must be in the same location as the servers that will mount it. **3. Configure** Set the size, from 32 GB to 20 TB, and choose the NFS protocols to enable: **NFSv4**, **NFSv3**, or both. A name is suggested for you; you can change it using letters, numbers, hyphens and underscores. Names must be unique within the project. **4. Create** Click **Create filesystem**. The filesystem opens on its detail page. Once it is provisioned, the page shows its endpoint, mount path and the mount command. ## Connecting servers to the storage network Servers reach the filesystem over a private storage network: a VLAN on top of the server's bond, with an address in your project's storage range. Creating the first filesystem or block volume in a location sets up this network for the project. A server joins it when it is deployed or reinstalled on a public network. * **New servers** deployed on a public network in the filesystem's project and location join automatically. * **Existing servers** deployed before the filesystem was created need a reinstall to join. Deploying or reinstalling with a [supported operating system](#supported-operating-systems) configures the storage VLAN and routes and installs the NFS client, so the server is ready to mount. > [!WARNING] > > Reinstalling erases the server's disks. Back up anything you need first. ## Mounting the filesystem The **Mount on a server** card on the filesystem page shows the command for your filesystem, with its endpoint and mount path filled in. Run it on each server that needs access: ```bash theme={null} sudo mkdir -p /mnt/shared-data sudo mount -t nfs -o vers=4 : /mnt/shared-data ``` To mount the filesystem on boot, add it to `/etc/fstab`. The `_netdev` option makes the system wait for the network before mounting: ```bash theme={null} echo ": /mnt/shared-data nfs vers=4,_netdev 0 0" | sudo tee -a /etc/fstab ``` Use `vers=3` if you only enabled NFSv3. Replace `/mnt/shared-data` if you want the filesystem somewhere else. > [!NOTE] > > Mounting requires an NFS client: `nfs-common` on Debian and Ubuntu, `nfs-utils` on RHEL-based systems. Supported operating systems install it on deploy and reinstall. Access is limited to servers on your project's storage network. There are no credentials to manage: any server on that network can mount the filesystem with read and write access, and `root` on the server keeps its permissions on the filesystem. ## Performance Measured with `fio` and direct I/O from a server with a 2×10 Gbps bond to a filesystem in the same location: | Workload | Default mount | With `nconnect=8` | | - | - | - | | Sequential read, 1 MiB | 1.0 GB/s | 2.3 GB/s | | Sequential write, 1 MiB | 1.0 GB/s | 1.5 GB/s | | Random read, 4 KiB | 40K IOPS | 63K IOPS | | Random write, 4 KiB | 27K IOPS | 25K IOPS | Results depend on the server's network capacity and the workload. By default, the mount uses a single TCP connection, and the bond carries it on one link. Add `nconnect=8` to open eight connections and spread the traffic over both links: ```bash theme={null} sudo mount -t nfs -o vers=4,nconnect=8 : /mnt/shared-data ``` To mount on boot with the same option, use it in the filesystem's `/etc/fstab` entry. If you already added an entry, edit it instead of appending a second line: ```text theme={null} : /mnt/shared-data nfs vers=4,nconnect=8,_netdev 0 0 ``` Use `vers=3` in both commands if you only enabled NFSv3. Throughput grows with the number of parallel requests. A single 4 KiB request takes about 0.3 ms to read and 0.9 ms to write, and creating a file takes about 2 ms. Keep workloads that create many small files or call `fsync` often, such as builds and package installs, on local disks. ## Resizing Filesystems can grow, but not shrink. Resizing is available through the API, up to 20 TB. ## Deleting Before deleting a filesystem, unmount it on every server and remove its `/etc/fstab` entry so the next boot doesn't wait for a filesystem that is no longer there: ```bash theme={null} sudo umount /mnt/shared-data ``` Then use **Delete filesystem** in the filesystem's actions menu and type its name to confirm. Deleting a filesystem permanently removes its data. Mounts left on servers stop working. ## Supported operating systems Automatic storage network configuration on deploy and reinstall is available for these images: * Debian 13 * Ubuntu 24.04 and 26.04 * AlmaLinux 9 and 10 * Rocky Linux 9 and 10 On other operating systems, contact support to configure the storage network. ## Current limits * A filesystem can be up to 20 TB. * Filesystems can grow but not shrink, and resizing isn't available in the dashboard yet. * A filesystem can only be mounted by servers in the same project and location. * Servers join the storage network on deploy or reinstall on a public network. Servers without a bond need a reinstall on a public network first. These limits are being worked on and will be lifted in upcoming releases. ## Pricing File storage is billed on provisioned capacity while the filesystem exists, whether or not it is mounted. The total for the size you choose is shown in the create flow before you confirm. Traffic between your servers and the filesystem is [free](/docs/storage/egress#file-storage). # Object storage Source: https://www.latitude.sh/docs/storage/object-storage S3-compatible object storage for scalable data management Object storage provides S3-compatible storage for your data on the Latitude.sh platform. Store and retrieve any amount of data using standard S3 APIs and tools you already know. ### Creating a bucket **1. Open the create bucket flow** Log in to the Latitude.sh dashboard and navigate to **Storage** > **Object storage** in the sidebar. Click **Create bucket**. **2. Choose a storage class** Select the storage class for your bucket (for example, **Standard**). The storage class determines the bucket's performance characteristics and pricing. **3. Choose a location** Pick the region and site where the bucket should live. Bucket data stays in the location you select. **4. Configure the bucket** Enter a **Bucket name** (see naming rules below). Optionally enable **Versioning** to keep object history, and **Object lock** to enforce write-once-read-many retention. Object lock requires versioning and lets you set a retention mode and period. **5. Create the bucket** Click **Create bucket** to finish. ### Versioning and object lock #### Versioning Versioning preserves every version of an object in your bucket, so deletes and overwrites can be recovered by restoring a prior version. Enable it when you want a safety net against accidental changes or deletions. > [!NOTE] > > Once versioning is enabled on a bucket, it cannot be disabled. #### Object lock (WORM) Object lock makes objects immutable for a retention period — write-once-read-many. Until the retention expires, the object cannot be deleted or modified, even by the bucket owner. Use it for regulatory compliance, audit trails, and protection against ransomware or accidental data loss. Two retention modes are available: * **GOVERNANCE** — Objects stay immutable until the retain-until date, but users with specific IAM permissions can override the lock. * **COMPLIANCE** — Objects stay immutable until the retain-until date and the lock cannot be reversed by any user, regardless of permissions. > [!WARNING] > > Object lock must be enabled when the bucket is created — it cannot be added to an existing bucket. Object lock also requires versioning to be enabled. #### Bucket naming rules Bucket names must follow these requirements: * Be between 3 and 63 characters long * Start with a lowercase letter or number * Contain only lowercase letters, numbers, dots (.), and hyphens (-) * Be globally unique ### Connecting to Object storage Use any S3-compatible tool or library to interact with your buckets. #### Connection details Find your connection details in the Object storage sidebar: * **Account ID**: Your unique account identifier * **S3 API endpoint**: The endpoint URL for S3 API requests. The format depends on the storage class: * Standard: `https://.s3.latitude.sh` * High performance: `https://objects..storage.sh` (for example, `https://objects.nyc.storage.sh`) #### Bucket credentials Each bucket gets an **access key** and **secret key** automatically when it's created, shown on the bucket detail page immediately after. > [!WARNING] > > The secret key is shown only once — right after the bucket is created. > Copy it before you refresh or leave the page. If you lose it, you can create a new [access key](#access-keys) to regain access to the bucket. The access key and endpoint remain visible on the bucket detail page after refresh, but the secret key does not. #### Access keys Access keys are project-scoped credentials that aren't tied to a single bucket's creation. To create one, navigate to the **Access keys** tab on the Object storage page and click **Create access key**. This requires a verified team and at least one existing bucket. **1. Choose a storage class and region** The key applies to buckets of the selected storage class in the selected region. **2. Choose an access scope** * **Full access** — read and write across all buckets of the selected storage class. * **Limited** — scope the key to specific buckets, each set to **Read-only** or **Read-write**. **3. Name and create the key** Give the key a name unique within the project, then create it. > [!WARNING] > > The secret key is shown only once, right after the key is created. Copy it before closing the dialog. Created keys appear in the **Access keys** tab with their access key ID, permission, scoped buckets, storage class, and status. ### Monitoring usage The Object storage dashboard displays the following metrics: #### Overview metrics * **Total Storage**: Total amount of data stored across all buckets * **Total Objects**: Number of objects stored across all buckets * **Class A Operations**: Write operations including PUT, POST, DELETE, and LIST requests * **Class B Operations**: Read operations including GET and HEAD requests #### Storage by bucket The Metrics tab shows a breakdown of storage usage per bucket, including the number of objects and percentage of total storage each bucket uses. ### Deleting a bucket A bucket must be empty before you can delete it. Delete every object in the bucket first, using the S3-compatible tool or library you connect with. For buckets with versioning enabled, also delete all object versions and delete markers. If any objects, versions, or delete markers remain, the deletion fails. **1. Open the delete flow** On the **Object storage** page, open the actions menu for the bucket and select **Delete bucket...**. You can also select **Delete bucket...** from the actions menu on the bucket detail page, or select **Delete** on the bucket's **Settings** tab. **2. Confirm the deletion** Enter the bucket name to confirm, then select **Delete**. Deletion is permanent. #### Deleting several buckets To delete more than one bucket at a time, select them from the bucket list: 1. On the **Object storage** page, select the checkbox next to each bucket you want to delete. To select every bucket that matches the current name filter, select the checkbox in the list header. 2. Select **Delete...** in the toolbar. 3. Enter `DELETE-ALL-BUCKETS` to confirm, then select **Delete**. If you selected only one bucket, enter `DELETE-BUCKET` instead. If a bucket can't be deleted, for example because it still has objects, the sheet lists it with the error. Buckets that were deleted are removed from the selection. After you fix the problem, enter the confirmation word again and select **Retry** to delete only the remaining buckets. If only one bucket is left, the word is `DELETE-BUCKET`. ### Pricing See the [storage pricing page](https://www.latitude.sh/pricing/storage) for details. # Contact support Source: https://www.latitude.sh/docs/support/contact-support Get help from the Latitude.sh AI agent or open a support ticket. When you need help, the Latitude.sh dashboard gives you two ways to reach us from a single place: an **AI agent** that can answer most questions instantly, and a **support ticket** form for anything that needs our team. To get started, go to **Support** in the dashboard sidebar, then click **Contact support**. You'll land in a chat with the Latitude.sh Agent. ## Chat with the AI agent The Latitude.sh Agent is an AI assistant that can resolve common questions about your account, servers, networking, billing, and more—often without waiting for a human. When you open the chat, you'll see a welcome screen with a few useful shortcuts: * **Documentation & API** — browse the docs, API reference, and guides. * **Talk to sales** — get in touch about infrastructure needs and pricing. Type your question in the message box and the agent will reply. If it finds something it can't solve, it will help create a support case for you—so you can move from a conversation to a ticket without starting over. ## Skip to a ticket If you already know you need a person, you don't have to chat first. Click **Skip to ticket** at the bottom of the chat composer to open the support ticket form directly. ## Open a support ticket The ticket form collects the details our team needs to help you quickly: **1. Choose a topic** Select the area your request relates to: **Compute**, **Networking**, **Billing**, **Sales**, **Feature request**, **Bugs**, or **Other**. This routes your ticket to the right team. **2. Add a subject** Enter a short summary of your issue. **3. Copy teammates (optional)** Add other members of your team to the ticket so they receive the same email updates. Only people who already belong to your team appear in the list. **4. Describe the problem** In the **Description** field, explain what you're seeing. The more detail you provide, the faster we can help. **5. Attach files (optional)** Add screenshots or logs to illustrate the problem. You can attach up to **5 files**, **50 MB each**. **6. Create the ticket** Click **Create ticket**. Your new ticket appears in the list on the **Support** page. > [!NOTE] > > Tickets created here are shared with your whole team, so any teammate can view and respond. ## Track your tickets The **Support** page splits your tickets into two tabs, each with a count: * **Team** — tickets associated with your team. Everyone on your team can view these and follow the conversation. Each row shows the ticket's status and when it was last updated; open any ticket to read replies and continue the conversation. * **Personal** — tickets you opened outside the dashboard, such as by emailing support directly, that aren't associated with your team yet. Only you can see these until you share them. Teammates you copied on a ticket get the same email updates no matter which tab it's in. ### Share a ticket with your team A ticket you opened outside the dashboard starts out personal—only you can see it. Share it so the rest of your team can view and respond: **1. Open the Personal tab** On the **Support** page, select **Personal** to see the tickets you created that aren't associated with your team yet. **2. Share the ticket** Click **Share** next to the ticket. It moves to the **Team** tab and becomes visible to your whole team. > [!NOTE] > > Only the person who created a ticket can share it, and closed tickets can't be shared. ## Grant temporary access for troubleshooting For issues that require our team to inspect your account directly, you can grant Latitude.sh staff temporary, time-limited access to your team. See [Support access](/docs/support/support-access) for details. # Support access Source: https://www.latitude.sh/docs/support/support-access Grant Latitude.sh staff temporary access to your team to help troubleshoot. Support access lets you allow Latitude.sh support staff to temporarily join your team account for troubleshooting and operational assistance. When some issues are easier to resolve from the inside, granting access lets our team see what you see and act on your behalf—without you sharing credentials. Access is **time-limited** and **fully under your control**: you choose how long it lasts, and you can revoke it at any time. When the grant expires—or when you revoke it—all Latitude.sh staff members are removed from your team automatically. ![Support access](https://mintcdn.com/latitudesh/GFXS0zOYd9W-zhet/images/product/54.Docs.SupportAccess.png?fit=max\&auto=format\&n=GFXS0zOYd9W-zhet\&q=85\&s=1ad09cd9997d7ab15705cfc8e5d7e246) ## Grant access **1. Open Support access** In the dashboard, go to **Support** and click **Support account access**, or navigate to **Settings → Members & access → Support access**. **2. Choose a duration** Pick how long staff should have access from the **Duration** dropdown: * **8 hours** * **24 hours** (default) * **48 hours** * **1 week** **3. Grant access** Click **Grant access**. The page updates to show an **Active** status and the date and time the access expires. While access is active, a reminder appears on the **Support** page letting you know that Latitude.sh staff can access your team, along with a link to manage it. ![Support access active](https://mintcdn.com/latitudesh/GFXS0zOYd9W-zhet/images/product/55.Docs.SupportAccessActive.png?fit=max\&auto=format\&n=GFXS0zOYd9W-zhet\&q=85\&s=3015307b19a81c7c8b3d1af839dcc9e8) ## Expiration Support access always ends—you never have to remember to turn it off. > [!NOTE] > > All Latitude.sh staff members are automatically removed from your team once access has expired. When the duration you selected elapses, the grant ends on its own and any Latitude.sh staff who joined your team are removed automatically. No action is required on your part. ## Revoke access early You don't have to wait for the timer to run out. While access is active, open the **Support access** page and click **Revoke access**. Staff members are removed from your team immediately. ## Related * [Contact support](/docs/support/contact-support) — chat with the AI agent or open a ticket. * [Team members](/docs/teams/members) — manage who belongs to your team and their roles. # Tags Source: https://www.latitude.sh/docs/tags Latitude.sh supports tagging, allowing you to categorize and manage your resources more effectively. Tags are key-value pairs that you can assign to your resources, making it easier to search, filter, and group them based on your specific needs. ## What are Tags? Tags are metadata labels that you can attach to your Latitude.sh resources. Tags help you: * Organize resources by purpose, owner, environment, or any other criteria relevant to your workflow * Quickly find and filter resources based on your assigned tags * Manage access control and permissions for grouped resources ## Naming rules Tag names must be unique within your team. The uniqueness check applies across all projects, not per-project. A tag created in one project is visible from every other project in the same team, and the same name can't be created twice. Two checks enforce this when you create a tag: * **Exact name match** within the team. Creating a tag with an already-used name fails with `is already taken`. * **Slug match** within the team. Names are normalized to a URL-safe slug (`Control-Plane`, `control plane`, and `CONTROL_PLANE` all collapse to `control-plane`); a slug collision fails with `is too similar to an existing tag name`. > [!NOTE] > > If a tag with the desired name already exists in your team, **reference it** instead of trying to create it again. Both the API and the Terraform provider expose data-source lookups for this. See [Using the API](#using-the-api) and [Using Terraform](#using-terraform). ## Supported resources Currently, you can assign tags to the following resources on Latitude.sh: * Servers * Virtual machines * Private networks (VLANs) * Firewalls Tagging support will be extended to more resources in the future. ## Creating and managing Tags You can create, edit, and delete tags through the Latitude.sh dashboard or API. ### Using the dashboard 1. Navigate to the resource (server, virtual machine, VLAN, or firewall) you want to tag. 2. Open the **Tags** select. 3. Start typing your tag to create a new one You can edit or remove tags by clicking on Manage tags. #### Bulk tagging servers To add or remove tags from multiple servers at once: 1. Go to the **Servers** list in your project. 2. Select the servers you want to tag by clicking the checkbox next to each one. 3. Click **Tags** in the toolbar that appears at the bottom of the screen. 4. Choose **Add tags** or **Remove tags**. 5. Select the tags you want to add or remove. 6. Click **Add tags** or **Remove tags** to apply your changes. Adding tags preserves any existing tags on each server. Removing tags only removes the selected tags. ### Using the API You can manage tags programmatically using the Latitude.sh API. Refer to the [Tags endpoint](https://www.latitude.sh/docs/api-reference/get-tags) for detailed instructions on creating, updating, and deleting tags using API calls. ### Using Terraform The Latitude.sh Terraform provider exposes both a `latitudesh_tag` resource (to create new tags) and a `latitudesh_tag` data source (to look up tags that already exist in your team). ```hcl theme={null} # Create a new tag resource "latitudesh_tag" "production" { name = "production" color = "#0066cc" } # Reference an existing tag (e.g. one a teammate created via the dashboard) data "latitudesh_tag" "control_plane" { name = "Control Plane" } ``` When applying tags to a server or private network, the `tags` attribute expects tag **IDs**, not names: ```hcl theme={null} resource "latitudesh_server" "web" { # ... other attributes ... tags = [ latitudesh_tag.production.id, data.latitudesh_tag.control_plane.id, ] } ``` Passing a name where an ID is expected returns `tag ID '' not found`. See the [Terraform provider documentation](https://registry.terraform.io/providers/latitudesh/latitudesh/latest/docs/resources/tag) for full schema details. ## Searching and filtering Resources by Tags Once you have assigned tags to your resources, you can use them to search and filter resources. ![Tags management interface](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/33.Docs25Q4.Tags.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=152ea9bb6c40c31c126e028ca9a36b97) ### Using the dashboard 1. Navigate to the resource type (servers, virtual machines, VLANs, or firewalls) you want to search or filter. 2. Click on the "Filter" and select Tags dropdown. 3. Select the desired tag to filter the resources. The list will update to display only the resources with the selected tag. ### Using the API You can search and filter resources by tags using the API. Refer to the specific API documentation for detailed instructions on constructing API calls with tag-based filtering. Here's an example on how you can retrieve a server with tag **k8s** ```shell theme={null} curl 'https://api.latitude.sh/servers?filter[tags]=k8s' --header 'Accept: application/json' --header 'Authorization: Bearer $API_TOKEN' ``` ## Best practices * Use a consistent naming convention to maintain clarity and avoid confusion. Many companies use tags as key-value pairs to manage growing environments. You can use key-value pairs by splitting the tag with `:`. Here are a key-value examples: * `env:production` `env:development`, ... * `k8s:etcd` `k8s:worker` `k8s:control-plane` * Assign tags that reflect your organization's resource management practices, such as cost allocation, ownership, or environment. * Regularly review and clean up unused or obsolete tags to keep your tagging system organized and efficient. By leveraging tags on Latitude.sh, you can streamline your resource management, access control, and reporting processes, making it easier to maintain and scale your infrastructure. # Creating a team Source: https://www.latitude.sh/docs/teams/create-team Before you start deploying on the Latitude.sh Platform, you need to create a **Team**. Teams allow you to organize multiple Projects and collaborate with other team members. If you've just signed up, you'll be taken straight to the **Create Team** page. Follow these steps: 1. Provide a name for your team. 2. Select the country where your company is registered. This determines the currency used for billing. Currently, only USD and BRL are supported. > [!WARNING] > > If you select Brazil, billing will be in BRL. For any other country, billing > defaults to USD. **This cannot be changed later**. 3. Choose your workload type to optimize the deployment environment. **Tip**: If you already have a team and want to create a new one, click the selector in the top left corner and choose **Create new team**. ![Team selector dropdown in the top left corner with Create new team option highlighted](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/38.Docs25Q4.CreateNewTeam.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=eda2e5dade9f2ad013927094324519a1) # Directory sync (SCIM) Source: https://www.latitude.sh/docs/teams/directory-sync Keep your team's members and roles in sync with your identity provider. Directory sync connects your identity provider to your Latitude.sh team over SCIM. When someone joins, changes roles, or leaves your company, their [team membership](/docs/teams/members) follows automatically, so you don't have to invite or remove people by hand. Directory sync works on its own or together with [SAML Single Sign-On (SSO)](/docs/teams/sso). SSO controls how members sign in; directory sync controls who is on your team and which role they have. > **Supported directory providers** > > * Okta > * Microsoft Entra ID > * Google Workspace > * OneLogin > * JumpCloud > * PingFederate > * Rippling > * CyberArk > * Any SCIM 2.0 provider **Pricing**: \$125/month. ## Setting up directory sync **Prerequisites**: * Your team must be verified. * You must be the team Owner or an Administrator. ### Step 1: Purchase directory sync **1. Navigate to directory sync settings** From the [dashboard](https://www.latitude.sh/dashboard), navigate to **Settings** → **Members & access** → **SSO & Directory Sync** tab. **2. Open directory sync setup** In the **Directory sync (SCIM)** row, click **Set up**. **3. Complete the purchase** Click **Set up** to complete the purchase. ### Step 2: Connect your directory After purchasing, the **Directory sync (SCIM)** row shows a **Pending** status. Click **Complete setup** to open the guided setup in a new tab, then select your identity provider and follow the steps to connect your directory. During the guided setup, map your identity provider's groups to Latitude.sh roles: **Administrator**, **Collaborator**, or **Billing**. These groups decide each member's role on your team. See [Roles](/docs/teams/members#roles) for what each role can do. Once the connection is complete, the row shows a **Connected** status and your directory starts syncing. ## Roles Your identity provider's groups decide each member's role: * A user in a mapped group gets that group's role. * A user who isn't in any mapped group gets the **Collaborator** role. * When a user moves to a different group, their role changes to match. To change a member's role, change their groups in your identity provider. Role changes made in the dashboard are replaced the next time your team syncs with your directory. ## How syncing works Members are matched to directory users by email address. As your identity provider reports changes, Latitude.sh applies them to your team: | In your identity provider | On your Latitude.sh team | | - | - | | A user is active in the directory | They're added to the team with the role from their groups | | A user's groups change | Their team role is updated to match | | A user is deactivated or removed from the directory | They're removed from the team | | A user's email changes | The new email is added as a new member and the previous email is removed from the team | An email change creates a new Latitude.sh user. The previous account, including its password, isn't carried over to the new email. Changes usually reach your team within moments. Latitude.sh also compares your team with your directory periodically to keep them consistent. The team Owner is never changed or removed by directory sync. Members added by directory sync can sign in right away. ## Adding and removing members Once directory sync is connected, your directory decides who is on your team. Members can't be invited manually. To add someone to your team, add them to your directory. Members who were on your team before you connected your directory, and aren't in it, aren't removed automatically. Instead, the **Directory sync (SCIM)** row shows that your team differs from the directory and offers a **Review** link. Click **Review** to see the members that would be added, have their role changed, or be removed to match your directory, then click **Apply** to make those changes to your team. ## Managing directory sync To manage your directory, click the **…** menu in the **Directory sync (SCIM)** row and select **Manage**. This opens the directory sync management page in a new tab, where you can update how your identity provider's groups map to roles and change other directory settings. If the connection needs attention, the row shows its status and the action to fix it: * **Validating**: Finish connecting your identity provider. Click **Complete setup**. * **Invalid credentials**: Update the credentials for your identity provider. Click **Update**. * **Not connected**: Complete the setup to resume syncing. Click **Complete setup**. # Team members Source: https://www.latitude.sh/docs/teams/members Team members have access to your account based on the Role they were assigned. ## Roles Your Team can have users in one of four roles, *Owner*, *Administrator*, *Collaborator*, and *Billing*. Owners have elevated permissions to manage and edit all aspects of a Team. Other members have limited permissions. ### Owner The person that created the account. Can see and edit everything. The person who signed up for the Latitude.sh account automatically becomes the Account Owner when the account is created. Teams can't have more than one Owner. ### Administrator Have view and edit rights to all account information and settings. Administrators manage all settings, including Billing. ### Collaborator Collaborators have access and edit rights to all the information on Servers and Networking. Collaborators can create new Servers, add SSH keys, request Additional IPs, and do all of the other server management actions, including deleting servers. They cannot view any account-related details, such as billing information, or add team members. ### Billing Users with the Billing role are only able to view and edit billing information and view and pay invoices. They can't see or modify servers or services on your account. ## Adding new members Follow these steps to add a member to your Team: 1. In the sidebar, go to **Settings**, then navigate to **Members & access** → **Members** tab, and click **Invite members**. You will see a list of people on your Team. If you are the only person on the Team, your account will be the **Owner**. 2. Enter the email address of the member you want to add, choose their role from the dropdown, and click **Send**. ![Team member invitation form showing email field, role dropdown selection, and Send button](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/39.Docs25Q4.InviteMembers.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=f842dff41d8bac88459a8374449090a1) # SAML Single Sign-On (SSO) Source: https://www.latitude.sh/docs/teams/sso Let your team members sign in to Latitude.sh through your identity provider. If your company uses an identity provider like Okta or OneLogin, your IT department will want to configure SAML. SAML SSO lets your team members sign in to the Latitude.sh dashboard through your identity provider, so access follows the accounts your company already manages. To also add, update, and remove [members](/docs/teams/members) from your identity provider, set up [Directory sync (SCIM)](/docs/teams/directory-sync). ## Get access to SAML SSO SAML SSO is available as an add-on that you can purchase directly from your dashboard. **Pricing**: \$125/month. Latitude.sh supports all major identity providers and then some. Here's a non-exclusive list of supported providers. If your identity provider is not listed here, reach out to [support](mailto:support@latitude.sh) for assistance. > **Supported SAML providers** > > * ADP > * Active Directory Federation Services > * Auth0 > * Azure Active Directory > * CAS > * ClassLink > * Cloudflare > * CyberArk > * Duo > * Generic OIDC > * Generic SAML > * Google > * JumpCloud > * Keycloak > * LastPass > * Login.gov > * miniOrange > * NetIQ > * Okta > * OneLogin > * Oracle > * PingFederate > * PingOne > * Rippling > * Salesforce > * Shibboleth > * Shibboleth Generic > * SimpleSAMLphp > * VMware ## Configuring SAML **Prerequisites**: * Your team must be verified. If it isn't yet, complete the verification process first. * You must be the team Owner or an Administrator. ### Step 1: Purchase SAML SSO **1. Navigate to SSO settings** From the [dashboard](https://www.latitude.sh/dashboard), navigate to **Settings** → **Members & access** → **SSO & Directory Sync** tab. **2. Open SSO setup** In the **SAML SSO** row, click **Set up**. **3. Review your domain** SSO is set up for the domain of your email address, for example `company.com`. Personal email domains, like `gmail.com`, aren't eligible. To use a domain other than your own email's, [contact support](/docs/support/contact-support). **4. Complete the purchase** Click **Set up** to complete the purchase. ### Step 2: Complete SSO configuration After purchasing, the **SAML SSO** row shows a **Pending** status. Click **Complete setup** to open the guided setup in a new tab, then select your identity provider and follow the steps to finish configuring SAML. Once your identity provider is connected, the row shows a **Connected** status along with your team's domains. ## Managing domains SSO applies to the domains listed in the **SAML SSO** row. To manage them, click the **…** menu in the row: * **Add domain**: Verify ownership of another domain through the guided setup. The domain is listed with its verification status until it's verified. * **Manage**: Open the SSO management page to update your identity provider connection. To remove a domain that hasn't been verified, click the trash icon next to it. Your team always keeps at least one domain. ## Authenticating with SAML Once you have configured SAML, your team members can use SAML SSO to log in. Type your email address on the authentication page and the **Continue with SAML SSO** button will become available. If you are already logged in to your identity provider, you will be automatically logged into Latitude.sh. If not, you will be redirected to your identity provider to finish authenticating. > [!WARNING] > > Once SAML SSO is active, users with emails from your team's domains will only be able to > authenticate through SAML SSO. # Bandwidth usage Source: https://www.latitude.sh/docs/usage/bandwidth The **Usage & billing** section on the Latitude.sh dashboard provides detailed insights into your project's data transfer, helping you monitor ingress and egress traffic. To view bandwidth usage, go to **Usage & Billing** → **Overview**, then click **View details**. ![Bandwidth usage dashboard showing total transfer, 95th percentile usage, and breakdown of inbound and outbound traffic](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/43.Docs25Q4.UsageOverview.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=b018f649dea13682e9ac9fd5d3863ccd) * **Total transfer:** Shows the total data transferred (both inbound and outbound). * **95th percentile:** Calculates billing based on the 95th percentile of usage, ignoring the top 5% of usage peaks to provide predictable costs. * **Inbound and outbound traffic:** Displays the amount of ingress and egress data used in the selected region. * **Usage chart**: The usage chart provides a visual breakdown of bandwidth over time within the current billing cycle. Each bar represents the amount of data transferred on specific days, helping you identify peak usage periods. * **Quota:** This is the total public data transfer your project can use before incurring overage charges. Each Latitude.sh server includes **20 TB of free egress traffic** and unlimited inbound ingress traffic. The 20 TB per server is added to your project's quota, which is shared among all servers in the same project and country. | Type | Amount added to quota | | :- | :- | | Free bandwidth | 20 TB per server | | Additional bandwidth | Sold in increments of 10 TB. [See pricing](https://www.latitude.sh/pricing/network) | > [!NOTE] > > Bandwidth is pooled even if servers are in different cities in the same > country. E.g., if you have servers in the US located in different cities, they > will share the same Bandwidth Quota. To check how much ingress and egress traffic a specific server has used, go to the server's page and click **View usage**. ![Clicking on View usage takes you to the server usage graph.](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/44.Docs25Q4.ServerUsage.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=f232cbf27ddd1f0803d27e962ea44258) ## Managing your quota You can increase and decrease your quota by going to the **Usage & Billing** → **Overview** → **View details**, and clicking **Manage quota** in the top right. Additional bandwidth is sold in increments of 10 TB and automatically increases your quota for the selected country. ![Bandwidth quota management interface showing options to increase or decrease quota in 10 TB increments](https://mintcdn.com/latitudesh/ZWurrjun6MJRTyC0/images/product/46.Docs25Q4.ManageQuota.png?fit=max\&auto=format\&n=ZWurrjun6MJRTyC0\&q=85\&s=c54ef3972aa3b6ea1a8698df64ee7fb9) ## Bandwidth alerts Bandwidth alerts notify users with the **Administrator** role when the bandwidth quota for a region exceeds 80%. This feature helps you monitor and manage usage more effectively. > [!WARNING] > > If you have multiple projects, enable this feature separately for each > project. Follow these steps to enable Bandwidth alerts: 1. Navigate to **Settings** > **Project** > **General** in your [Project Settings](/docs/projects/project-settings). 2. Under **Bandwidth alerts**, click **Enable**. Once enabled, administrators will receive up to three email notifications per week for any region expected to exceed the quota. Alerts stop automatically if you increase the project's quota or reduce usage below 80%. ## Overages For all [regions](https://www.latitude.sh/locations), overage Bandwidth costs **\$0.01 per GB** that goes over your quota. By buying Bandwidth Packages, you can considerably reduce the cost per GB to as little as \$0.00125. Bandwidth Packages can be added to a project in increments of 10 TB. Pricing for each country is available [here](https://www.latitude.sh/pricing/network). # Backups and restore Source: https://www.latitude.sh/docs/vms/backups-and-restore Capture point-in-time backups of a virtual machine's disk and restore them into new virtual machines. A backup captures a point-in-time copy of a virtual machine's disk. You can restore that backup into a new virtual machine whenever you need to recover data or clone the machine. Backups run in the background and don't affect the running instance. ## Creating a backup **1. Start a backup** Open the virtual machine and click **Actions > Back up...**, or open the **Backups** tab and click **Create backup**. **2. Confirm** Review the details and click **Create backup**. The machine keeps running while the backup is captured in the background. ## Backups tab The **Backups** tab on the virtual machine's detail page lists every backup as an expandable card showing when it was created, its status, and its size. Expand a card to see the virtual machines restored from that backup, each linking to the machine it created. You can also copy a backup's ID from its card. Each backup moves through the following statuses: * **Creating**: The backup is being captured. It can't be restored or deleted yet. * **Ready**: The backup is complete and available to restore or delete. * **Failed**: The backup didn't complete. You can delete it, but you can't restore from it. * **Archived**: Deletion was requested and the backup is being removed. While a backup is being created or removed, the tab updates on its own, so statuses and sizes refresh without a manual reload. ## Restoring from a backup Restoring always creates a new virtual machine and leaves your original machine unchanged. **1. Open the restore modal** On the **Backups** tab, expand the backup you want and click the restore action. The backup must be in the **Ready** status. **2. Name the new machine (optional)** Enter a name for the restored machine, or leave it blank to generate one from the source machine. **3. Choose a region** Pick a region for the new machine. The picker lists the locations your plan is available in; out-of-stock locations are disabled and show a **No stock** badge. **4. Start the restore** Click **Restore**. The restore runs in the background, and the new machine appears in the backup's restore list as it's created. ## Deleting a backup On the **Backups** tab, expand a backup, click the delete action, and confirm. A backup can be deleted once it's in the **Ready** or **Failed** status. Deleting is permanent and can't be undone, but virtual machines you've already restored from the backup aren't affected. # Monitoring Source: https://www.latitude.sh/docs/vms/monitoring Track your virtual machine's performance with real-time metrics for CPU, memory, network, and disk. Track your virtual machine's performance metrics directly from the dashboard. ## Overview The Monitoring section on your VM's overview page shows key metrics at a glance: * **CPU usage**: CPU utilization percentage * **Memory usage**: Memory consumption percentage * **Network received**: Incoming traffic in bytes per second * **Disk read**: Read operations in bytes per second ## Monitoring details page For detailed charts and historical data, open the monitoring details page. **1. Access monitoring details** Go to the **Virtual machines** section in the sidebar menu and select the virtual machine you want to monitor. **2. Open monitoring details** In the Monitoring section on the VM overview page, click **View details**. The monitoring details page displays time-series charts for: * **CPU usage**: CPU utilization over time * **Memory usage**: Memory consumption over time * **Network received**: Incoming traffic in bytes per second * **Disk read**: Read operations in bytes per second ## Time period Use the dropdown selector to adjust the time range: * 5 minutes * 15 minutes * 1 hour * 24 hours # Virtual machines Source: https://www.latitude.sh/docs/vms/virtual-machines Latitude.sh virtual machines are optimized for general-purpose computing workloads. ![Virtual machine deployment page](https://mintcdn.com/latitudesh/T4X5auQmsIdYbWED/images/product/53.Docs25Q4.VMCPUdeploy.png?fit=max\&auto=format\&n=T4X5auQmsIdYbWED\&q=85\&s=b5ee658c3f4d583bfbeb96db89383e5f) ## Deploying a virtual machine Set up your virtual machine with these steps: **1. Access the instance creation page** [Log in to the dashboard](https://www.latitude.sh/dashboard), select a project, navigate to **Virtual machines** in the sidebar and click **Create instance**. **2. Choose plan and location** Select the configuration and location based on your workload needs. **3. Select an operating system** Choose the operating system for your instance from the available distributions and versions. **4. Set billing and instance details** Select the billing method (hourly or monthly). Choose the number of instances to deploy (1-5) and name them. Names are auto-generated based on your plan and location (e.g., `cpu-vm-ash-1`, `cpu-vm-ash-2`). You can customize the first name and subsequent instances follow the same pattern (e.g., `web`, `web-2`, `web-3`). When deploying multiple instances, the pricing summary shows the total cost and unit price per instance. **5. Deploy the instances** Click **Create** to deploy your virtual machines. All instances deploy in parallel. ## Logging into your instance **1. Connect via SSH** Go to the instance details page to find your access credentials. Use the username, password, and public IP provided to connect via SSH. The default SSH port is 22. Root access is disabled, so log in with the provided username and use sudo to switch to root if needed. ## Power management To power cycle your virtual machine, go to the instance's overview page and click on the status dropdown. Choose one of the available options. > [!NOTE] > > Shutting down a virtual machine does not pause billing. To avoid charges, you > have to delete the instance instead. ## Resizing a virtual machine You can vertically upgrade a virtual machine to a larger plan, scaling its vCPU, RAM, and disk. Upgrade from the dashboard or through the API. Resizing is upgrade-only: the target plan's vCPU, memory, and storage must each be greater than or equal to your current plan. Nothing can shrink, because the underlying volume can't be reduced. Resizing is disruptive and runs asynchronously: the instance is powered off, migrated to the new plan, and powered back on. Once the disk grows, the guest operating system expands its own partition and filesystem to use the additional space. The managed OS images handle this automatically on boot. ### From the dashboard Open the instance's detail page and select **Upgrade...** next to the **Plan** property. Choose a larger plan from the list of eligible plans, type the instance name to confirm, and select **Upgrade plan**. Upgrades are only available from a stable state, so the instance must be running or stopped. ### Through the API Send a `PATCH` request to the [Update a virtual machine](https://www.latitude.sh/docs/api-reference/update-virtual-machine) endpoint with the `plan` attribute set to the target plan. Send `plan` on its own — you can't combine a resize with a `name`, `tags`, or `billing` change in the same request. The endpoint returns `202 Accepted` and continues the work in the background. If a resize is already in progress for the instance, it returns `409 Conflict`. ## Backups and restore Capture point-in-time backups of a virtual machine's disk and restore them into new virtual machines whenever you need to recover data or clone a machine. For the full workflow, see [Backups and restore](/docs/vms/backups-and-restore). ## Monitoring Track your virtual machine's performance metrics including CPU usage, memory usage, storage operations, and network traffic from the monitoring section on your VM's overview page. For detailed charts and historical data, see [Monitoring](/docs/vms/monitoring). ## Firewall Only one firewall can protect a virtual machine at a time, managed from the **Firewall assignment** section on the VM's overview page. For the full workflow, see [Firewall](/docs/networking/firewall). ## Deleting a virtual machine **1. Delete the instance** Click **Actions > Delete** and confirm the deletion.