diff --git a/deploy-static-site/action.yaml b/deploy-static-site/action.yaml index 6384f4b..ab11aa4 100644 --- a/deploy-static-site/action.yaml +++ b/deploy-static-site/action.yaml @@ -11,6 +11,11 @@ inputs: description: 'Domain the site is served at (e.g. toph.so)' required: true + flake-output: + description: 'Flake output to build (e.g. default, docs)' + required: false + default: 'default' + nomad-addr: description: 'Nomad API address' required: false @@ -50,7 +55,7 @@ runs: - name: Build site shell: bash - run: nix build .#default --out-link result-site + run: nix build ".#${{ inputs.flake-output }}" --out-link result-site - name: Sign and push Nix closure to S3 cache shell: bash @@ -76,10 +81,13 @@ runs: - name: Deploy Nomad job shell: bash run: | - python3 "${{ github.action_path }}/generate-job.py" | nomad job run -json - + nix eval --raw --impure \ + --expr "import ${{ github.action_path }}/nomad-job.nix" \ + | nomad job run -json - env: NOMAD_ADDR: ${{ inputs.nomad-addr }} DOMAIN: ${{ inputs.domain }} + SITE_HASH: ${{ env.SITE_HASH }} SERVER_IMAGE: ${{ inputs.server-image }} DATACENTER: ${{ inputs.datacenter }} S3_BUCKET: ${{ inputs.s3-bucket }} diff --git a/deploy-static-site/generate-job.py b/deploy-static-site/generate-job.py deleted file mode 100644 index 3317d76..0000000 --- a/deploy-static-site/generate-job.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python3 -""" -Generate a Nomad job JSON for a static site deployment. -Reads from environment variables, prints JSON to stdout. -Pipe to: nomad job run -json - -""" - -import json -import os -import sys - -domain = os.environ["DOMAIN"] -site_hash = os.environ["SITE_HASH"] -server_image = os.environ.get("SERVER_IMAGE", "registry.toph.so/static-server:latest") -datacenter = os.environ.get("DATACENTER", "contabo") -s3_bucket = os.environ["S3_BUCKET"] - -job_id = "site-" + domain.replace(".", "-") - -startup_cmd = ( - f"mkdir -p /var/www && " - f"aws s3 cp s3://{s3_bucket}/sites/{domain}/{site_hash}.tar.gz - " - f"| tar xz -C /var/www/ && " - f"exec static-web-server --port 8080 --root /var/www" -) - -nomad_template_data = ( - '{{ with nomadVar "static-sites/s3" }}' - "AWS_ACCESS_KEY_ID={{ .access_key }}\n" - "AWS_SECRET_ACCESS_KEY={{ .secret_key }}\n" - "AWS_ENDPOINT_URL={{ .endpoint }}\n" - "{{ end }}" -) - -job = { - "Job": { - "ID": job_id, - "Name": job_id, - "Namespace": "static-sites", - "Type": "service", - "Datacenters": [datacenter], - "Update": { - "MinHealthyTime": 5000000000, # 5s in nanoseconds - "HealthyDeadline": 60000000000, # 60s in nanoseconds - "MaxParallel": 1, - }, - "TaskGroups": [ - { - "Name": "site", - "Count": 1, - "Networks": [ - { - "DynamicPorts": [ - {"Label": "http", "To": 8080} - ] - } - ], - "Services": [ - { - "Name": job_id, - "Provider": "nomad", - "PortLabel": "http", - "Tags": [ - "traefik.enable=true", - f"traefik.http.routers.{job_id}.rule=Host(`{domain}`)", - f"traefik.http.routers.{job_id}.entrypoints=websecure", - f"traefik.http.routers.{job_id}.tls.certresolver=letsencrypt", - ], - "Checks": [ - { - "Type": "http", - "Path": "/", - "Interval": 30000000000, # 30s - "Timeout": 5000000000, # 5s - } - ], - } - ], - "Tasks": [ - { - "Name": "server", - "Driver": "docker", - "Config": { - "image": server_image, - "command": "/bin/bash", - "args": ["-c", startup_cmd], - "ports": ["http"], - }, - "Templates": [ - { - "EmbeddedTmpl": nomad_template_data, - "DestPath": "secrets/s3.env", - "Envvars": True, - } - ], - "Resources": { - "CPU": 100, - "MemoryMB": 128, - }, - } - ], - } - ], - } -} - -json.dump(job, sys.stdout, indent=2) -print() diff --git a/deploy-static-site/nomad-job.nix b/deploy-static-site/nomad-job.nix new file mode 100644 index 0000000..ee3e6c0 --- /dev/null +++ b/deploy-static-site/nomad-job.nix @@ -0,0 +1,86 @@ +let + domain = builtins.getEnv "DOMAIN"; + siteHash = builtins.getEnv "SITE_HASH"; + serverImage = builtins.getEnv "SERVER_IMAGE"; + datacenter = builtins.getEnv "DATACENTER"; + s3Bucket = builtins.getEnv "S3_BUCKET"; + + jobId = "site-" + builtins.replaceStrings [ "." ] [ "-" ] domain; + + startupCmd = + "mkdir -p /var/www && " + + "aws s3 cp s3://${s3Bucket}/sites/${domain}/${siteHash}.tar.gz - " + + "| tar xz -C /var/www/ && " + + "exec static-web-server --port 8080 --root /var/www"; + + templateData = + "{{ with nomadVar \"static-sites/s3\" }}" + + "AWS_ACCESS_KEY_ID={{ .access_key }}\n" + + "AWS_SECRET_ACCESS_KEY={{ .secret_key }}\n" + + "AWS_ENDPOINT_URL={{ .endpoint }}\n" + + "{{ end }}"; + + job = { + Job = { + ID = jobId; + Name = jobId; + Namespace = "static-sites"; + Type = "service"; + Datacenters = [ datacenter ]; + Update = { + MinHealthyTime = 5000000000; + HealthyDeadline = 60000000000; + MaxParallel = 1; + }; + TaskGroups = [ + { + Name = "site"; + Count = 1; + Networks = [ + { DynamicPorts = [ { Label = "http"; To = 8080; } ]; } + ]; + Services = [ + { + Name = jobId; + Provider = "nomad"; + PortLabel = "http"; + Tags = [ + "traefik.enable=true" + "traefik.http.routers.${jobId}.rule=Host(`${domain}`)" + "traefik.http.routers.${jobId}.entrypoints=websecure" + "traefik.http.routers.${jobId}.tls.certresolver=letsencrypt" + ]; + Checks = [ + { Type = "http"; Path = "/"; Interval = 30000000000; Timeout = 5000000000; } + ]; + } + ]; + Tasks = [ + { + Name = "server"; + Driver = "docker"; + Config = { + image = serverImage; + command = "/bin/bash"; + args = [ "-c" startupCmd ]; + ports = [ "http" ]; + }; + Templates = [ + { + EmbeddedTmpl = templateData; + DestPath = "secrets/s3.env"; + Envvars = true; + } + ]; + Resources = { + CPU = 100; + MemoryMB = 128; + }; + } + ]; + } + ]; + }; + }; +in +builtins.toJSON job