How to use the UpCloud API to manage your UpCloud servers.
If you have not read my previous posts I have now moved my blog etc to the awesome UpCloud host. Sign up using this link to get $25 free credit.
I recently compared Digital Ocean, Vultr and UpCloud Disk IO here and UpCloud came out on top by a long way (read the blog post here).
Here is my blog post on moving from Vultr to UpCloud.
Spoiler: UpCloud performance is great.
I have never had an UpCloud page load take longer than 2 seconds since moving.
UpCloud API
UpCloud has an API that we can opt into to using where we can manage servers. Read the official UpCloud API documentation here.
The API allows you to control:
- Accounts
- Pricing
- Zones
- Timezones
- Plans
- Servers
- Storages
- IP-Addresses
- Firewall
- Tags
- etc
Create a sub-account to query the API
You should create a new user account (in the UpCloud dashboard) just for API access. I created two accounts for use on my server and on my home laptop and my server (and set a limiting IP(s) that can access it).
Create a Sub Account for API Access
Login to your UpCloud account (create an account here and get $25 free credit),
- Click My Accounts,
- Click User Accounts,
- Click Change on your user and enable API connections.
- TIP: Set up an IP rule to limit access to your API for security (I set up a VPN to get a static IP on my dynamic IP Internet host at home)).
- Save the changes
TIP: Lockdown the account to have the minimum permissions required.
e.g
- Disable access to the control panel (Untick).
- Allow API Connections (Tick) and specify an IP
- Disable access to billing contact (Untick).
- Disable access to billing section in the control panel (Untick).
- Disable allowing of emails to billing contact (Untick).
- Allow or Remove access to all server (or manually add access to desired servers)
- Allow or Remove access to modify storage (or manually allow or remove access to desired storage)
- etc
Save the account.
Now let’s make our first API call
I use OSX and I use the awesome Paw API testing tool from https://paw.cloud (This is not a plug, they are awesome). Postman is a popular API testing tool too. Any good programing language or CLI will allow you to send API requests.
First, let’s prepare the authorization string (this is a Base64 encoded combination of your username and password) read more here.
- Head over to https://www.base64encode.org/
- Click the Encode tab
- Add your “username:password” (without the quotes).
- Click Encode
A Base64 string will be outputted 🙂
e.g > eW91cmFwaXVzZXJuYW1lOnlvdXJzdXBlcnNlY3VyZXBhc3N3b3Jk
fyi
You can encode also Encode and Decode Base64 from the Ubuntu Command line
Encode Base64 from the CLI Sample
Decode Base64 from the CLI Sample
Now we can add an “Authorization Basic” token to the API request in Paw.
A quick test of the UpCloud Prices API endpoint https://api.upcloud.com/1.2/price reveals the API is working.
I can now see a full breakdown of my service prices in JSON 🙂
Query My Account
OK, Let’s see how much credit I have left by querying the https://api.upcloud.com/1.2/account, I duplicated the item in Paw and changed the URL to https://api.upcloud.com/1.2/account but no data returned?
I had to enable “Access to Billing section in Control Panel” for the user before this data returned from the API (make sense).
> HTTP/1.1 200 OK
Query (GET)
GET /1.2/account HTTP/1.1 Host: api.upcloud.com User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.5) NSURLConnection/1452.23 Authorization: Basic *******************************************
Output
HTTP/1.1 200 OK Date: Sun, 17 Jun 2018 04:23:32 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 91 Server: Apache { "account" : { "credits" : 2500.00, "username" : "yourapiusername" } }
“2500.00” = cents ($25)
Query All of Your Servers
Ok, Let’s get server information by querying https://api.upcloud.com/1.2/server
Query (GET)
GET /1.2/server HTTP/1.1 Host: api.upcloud.com User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.5) NSURLConnection/1452.23 Authorization: Basic ##############base64hash##############
Output
HTTP/1.1 200 OK Date: Sun, 17 Jun 2018 04:32:22 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 1154 Server: Apache { "servers" : { "server" : [ { "core_number" : "1", "hostname" : "server1nameredacted.com", "license" : 0, "memory_amount" : "2048", "plan" : "1xCPU-2GB", "plan_ipv4_bytes" : "3472464313", "plan_ipv6_bytes" : "166293599", "state" : "started", "tags" : { "tag" : [ "tag1" ] }, "title" : "server1nameredacted.com", "uuid" : "########-####-####-####-############", "zone" : "us-chi1" }, { "core_number" : "1", "hostname" : "server2nameredacted.com", "license" : 0, "memory_amount" : "1024", "plan" : "1xCPU-1GB", "plan_ipv4_bytes" : "198911", "plan_ipv6_bytes" : "19742", "state" : "started", "tags" : { "tag" : [ "tag2" ] }, "title" : "server1nameredacted.com", "uuid" : "########-####-####-####-############", "zone" : "us-chi1" } ] } }
Query Server Information
I have redated the UUID’s for my servers but once you know them you can query them by hitting https://api.upcloud.com/1.2/server/########-####-####-####-############
Query (GET)
Output
HTTP/1.1 200 OK Date: Sun, 17 Jun 2018 04:45:14 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 1656 Server: Apache { "server" : { "boot_order" : "cdrom,disk", "core_number" : "1", "firewall" : "on", "host" : redacted, "hostname" : "server1nameredacted.com", "ip_addresses" : { "ip_address" : [ { "access" : "private", "address" : "##.#.#.###", "family" : "IPv4" }, { "access" : "public", "address" : "###.###.###.###", "family" : "IPv4", "part_of_plan" : "yes" }, { "access" : "public", "address" : "####:####:####:####:####:####:########", "family" : "IPv6" } ] }, "license" : 0, "memory_amount" : "2048", "nic_model" : "virtio", "plan" : "1xCPU-2GB", "plan_ipv4_bytes" : "3519033266", "plan_ipv6_bytes" : "168200052", "state" : "started", "storage_devices" : { "storage_device" : [ { "address" : "virtio:0", "boot_disk" : "0", "part_of_plan" : "yes", "storage" : "########-####-####-####-############", "storage_size" : 50, "storage_title" : "system", "type" : "disk" } ] }, "tags" : { "tag" : [ "fearby" ] }, "timezone" : "Australia/Sydney", "title" : "server1nameredacted.com", "uuid" : "########-####-####-####-############", "video_model" : "cirrus", "vnc" : "off", "vnc_password" : "#########################", "zone" : "us-chi1" } }
The servers name, IPv4 and IPV6 network adapters are listed, CPU(s), Memory, Disk Sized and UUID’s are all visible 🙂
Surprisingly the VNC password is visible (enabling access to the root console).
TIP: Ensure your API account is safe and secure.
Query Storage Information
Now, Let’s query the storage with the GUID from above by querying https://api.upcloud.com/1.2/storage/########-####-####-####-############
Query (GET)
GET /1.2/storage/########-####-####-####-############ HTTP/1.1 Host: api.upcloud.com User-Agent: Paw/3.1.7 (Macintosh; OS X/10.13.5) NSURLConnection/1452.23 Authorization: Basic ##############base64hash##############
Output
HTTP/1.1 200 OK Date: Sun, 17 Jun 2018 04:53:36 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 559 Server: Apache { "storage" : { "access" : "private", "backup_rule" : {}, "backups" : { "backup" : [ "########-####-####-####-############" ] }, "license" : 0, "part_of_plan" : "yes", "servers" : { "server" : [ "########-####-####-####-############" ] }, "size" : 50, "state" : "online", "tier" : "maxiops", "title" : "system", "type" : "normal", "uuid" : "########-####-####-####-############", "zone" : "us-chi1" } }
I can see information about the storage’s assigned server and backups 🙂
Query Backup Information
Backup storage can be queried with the same storge API endpoint https://api.upcloud.com/1.2/storage/########-####-####-####-############
Query (GET)
Output
HTTP/1.1 200 OK Date: Sun, 17 Jun 2018 05:01:11 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 412 Server: Apache { "storage" : { "access" : "private", "created" : "2018-06-16T04:47:56Z", "license" : 0, "origin" : "########-####-####-####-############", "servers" : { "server" : [] }, "size" : 50, "state" : "online", "title" : "On-Demand Backup", "type" : "backup", "uuid" : "########-####-####-####-############", "zone" : "us-chi1" } }
Rename Backup
One thing that I would like to be able to do is to rename on-demand backups in the UpCloud dashboard (this is not a feature yet) but I can rename manual backup’s in the API though 🙂
Boring “On-Demand Backup” label.
I tried sending JSON to https://api.upcloud.com/1.2/storage/########-####-####-####-############ to rename a backup but kept getting an error?
JSON
{
> “storage”: {
> “title”: “Latest manual backup , Working NGINX, PHP, MySQL w Tweaks”,
> “size”: “50”
> }
> }
Result
> “error_code” : “CONTENT_TYPE_INVALID”,
> “error_message” : “The Content-Type header has an invalid value.”
I googled and found an old manual for UpClouds API (official support here).
I added these missing content-type headers (108 was the length in chars of the payload)
> Content-Type: application/json; Charset=UTF-8' > Content-Length: 108
Still no go?
I think the content-length value is wrong, more here.
I fixed it, it turned out I had a semicolon in the Content-Type value. The JSON RFC always assumes that Content-Type is UTF8 encoded (more here).
This Fails
This Works
Content-Type: application/json
Now I can rename my Backup (storage). I manually calculated the length of the JSON payload and added a “Content-Length” header and value.
Query (PUT)
Output
HTTP/1.1 202 ACCEPTED Date: Sun, 17 Jun 2018 05:47:02 GMT Content-Type: application/json; charset=UTF-8 Connection: close Content-Length: 453 Server: Apache { "storage" : { "access" : "private", "created" : "2018-06-16T04:47:56Z", "license" : 0, "origin" : "########-####-####-####-############", "servers" : { "server" : [] }, "size" : 50, "state" : "online", "title" : "Latest manual backup , Working NGINX, PHP, MySQL w Tweaks", "type" : "backup", "uuid" : "########-####-####-####-############", "zone" : "us-chi1" } }
Success 🙂
Create a Backup
Backups can be performed with a “/backup” added to the end of the query string.
Query (POST)
Output
Success (UpCloud GUI)
Conclusion
UpCloud does have great API docs.
I can easily integrate this into bash scripts to manage my servers via API and a future Java app for managing servers.
Paw does give CURL output to allow me to copy working API’s for use in BASH 🙂
More to come
- BASH Script to Deploy and configure a server on UpCloud via Initialization scripts (or manual) (1 week)
- JAVA App to manage your server (3 months)
If you are signing up for UpCloud please consider using my referral code and get $25 credit for free.
Read my setup guide here.
https://www.upcloud.com/register/?promo=D84793
I hope this guide helps someone.
Ask a question or recommend an article
[contact-form-7 id=”30″ title=”Ask a Question”]
Revision History
V1.1 updated typo
v1.0 Initial Post.