Contents

Deploy on Google Cloud, AWS or Azure Enterprise

On Google Cloud, AWS and Azure you run the team server as a unikernel, a tiny VM that boots straight into gitta. There is no shell, no SSH and nothing else installed, which minimizes the attack surface.

Why a unikernel

A normal VM runs an operating system with many services, users and tools. Each one needs updates and is a way in. The gitta unikernel image holds the Nanos kernel and the gitta server, nothing else. Nobody can log in to it.

To change a server, build a new image and replace the VM. The deploy script does both.

Before you start

Google Cloud

  1. Make a storage bucket for images, in the region you will use.
     Terminal
    $ gcloud storage buckets create gs://example-gitta-images --location=europe-north1
  2. Make a service account with the roles Compute Admin, Storage Admin and Service Account User. Save its key file.
  3. Deploy two servers in two zones.
     Terminal
    $ export GOOGLE_APPLICATION_CREDENTIALS=~/gitta-deploy-key.json
    $ export GCP_PROJECT=example-project GCP_ZONE=europe-north1-a GCP_BUCKET=example-gitta-images
    $ export GCP_ZONES=europe-north1-a,europe-north1-b COUNT=2
    $ export GITTA_TLS_CERT=fullchain.pem GITTA_TLS_KEY=privkey.pem
    $ export GITTA_LICENSE_FILE=example.license
    $ ./deploy.sh gcp ./gitta gitta
    token written to ./gitta-server.token
    signing key written to ./gitta-server.signing-key
    Image creation succeeded gitta.
    Instance creation succeeded gitta-1.
    Instance creation succeeded gitta-2.
    started 2 server(s). Find the addresses with: ops instance list -t gcp -c <config>
  4. Reserve the VMs' addresses as static addresses and point your DNS names at them.
     Terminal
    $ gcloud compute addresses create gitta-1 --addresses=<address of gitta-1> --region=europe-north1

AWS

  1. Make an S3 bucket for images.
     Terminal
    $ aws s3 mb s3://example-gitta-images --region eu-north-1
  2. Create the vmimport role that AWS uses to import VM images. Follow the AWS guide "Required service role for VM Import". Give it read access to the bucket.
  3. The user that deploys needs EC2 and S3 rights, and the EBS rights ebs:StartSnapshot, ebs:PutSnapshotBlock, ebs:CompleteSnapshot.
  4. Deploy.
     Terminal
    $ export AWS_PROFILE=gitta AWS_REGION=eu-north-1 AWS_BUCKET=example-gitta-images COUNT=2
    $ export GITTA_TLS_CERT=fullchain.pem GITTA_TLS_KEY=privkey.pem GITTA_LICENSE_FILE=example.license
    $ ./deploy.sh aws ./gitta gitta
  5. Allocate an Elastic IP for each server, associate it, and point your DNS names at them.

Azure

  1. Make a resource group and a storage account.
     Terminal
    $ az group create -n gitta -l swedencentral
    $ az storage account create -n examplegittaimages -g gitta -l swedencentral --sku Standard_LRS
  2. Make a service principal with the Contributor role on the resource group.
  3. Deploy.
     Terminal
    $ export AZURE_SUBSCRIPTION_ID=… AZURE_TENANT_ID=… AZURE_CLIENT_ID=… AZURE_CLIENT_SECRET=…
    $ export AZURE_LOCATION=swedencentral AZURE_RESOURCE_GROUP=gitta AZURE_BASE_GROUP_NAME=gitta
    $ export AZURE_STORAGE_ACCOUNT=examplegittaimages AZURE_STORAGE_ACCESS_KEY=…
    $ export GITTA_TLS_CERT=fullchain.pem GITTA_TLS_KEY=privkey.pem GITTA_LICENSE_FILE=example.license COUNT=2
    $ ./deploy.sh azure ./gitta gitta
  4. Attach a static public IP to each VM's network interface, and point your DNS names at them.

Settings for deploy.sh

VariableUse
COUNTNumber of servers. Default 1. Use 2 or 3 for several servers.
GCP_ZONESZones on Google Cloud to spread the servers over, comma separated.
FLAVORVM size. The defaults are e2-small, t3.small and Standard_B2ts_v2.
GITTA_TOKENSAdmin tokens. If empty, one is made and written to ./gitta-server.token.
GITTA_SIGNING_KEYIf empty, ./gitta-server.signing-key is used or made. Keep it for the next deploy.
GITTA_TLS_CERT, GITTA_TLS_KEYWith these, the server serves HTTPS on port 8443. Without them, HTTP on port 8080, for use behind a TLS load balancer.
GITTA_LICENSE_FILEYour licence.
ARCHamd64 (default) or arm64, to match the server program.
Secrets are part of the imageThe admin tokens, the signing key and the TLS private key are built into the VM image. Anyone who can read or copy images in your cloud account can read them, for example on Google Cloud with the Compute Image User role, on AWS with the right to copy the AMI or its snapshot, and on Azure with read access to the image gallery. A private image is still a copy of the secrets.

Treat the image like the secrets in it:

Kubernetes keeps these secrets in a Kubernetes Secret instead, provided at start, not stored in an image. Use the Helm chart where that difference matters.

Try it on your own machine

deploy.sh local boots the same image under QEMU, on port 8080 or 8443.

 Terminal
$ ./deploy.sh local ./gitta

Cost

One small VM per server. Delete the VMs and images when you stop using them.