diff --git a/.gitignore b/.gitignore index adf71715..03b9d83a 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ **/config.yaml **/signing.yaml .DS_Store +# digital ocean custom values +private.yml diff --git a/ansible/Pipfile b/ansible/Pipfile index 882b7e17..e2ae277a 100644 --- a/ansible/Pipfile +++ b/ansible/Pipfile @@ -11,6 +11,8 @@ ansible-lint = "==6.4.0" yamllint = "==1.27.1" ansible-core = "==2.13" docker = "*" +boto3 = "*" +jmespath = "*" [dev-packages] diff --git a/ansible/README.md b/ansible/README.md new file mode 100644 index 00000000..564498b4 --- /dev/null +++ b/ansible/README.md @@ -0,0 +1,48 @@ +### Playbooks to install browsertrix + +#### DigitalOcean + +To install browsertrix on [DigitalOcean](playbooks/do_setup.yml) you will need to the following: + +* Install [ansible](https://www.ansible.com) +* Set up a DigitalOcean API token and save it in your environment as `DO_API_TOKEN` +* Set up a Spaces ACCESS and SECRET KEY and save them in your environment as `DO_AWS_ACCESS_KEY` and `DO_AWS_SECRET_KEY` +* make a copy of [group_vars/do/private.yml.example](group_vars/do/private.yml.example) to [group_vars/do/private.yml](group_vars/do/private.yml) + + +##### Digital Ocean Variables + +See Known Issues below. + +The first running of the playbook will place variables under your tmp directory in the following format YYYY-MM-DD@:HH:MMd_ocean*. Content of these files will need to be added to the [group_vars/do/private.yml](group_vars/do/private.yml) or else run as an `-e` extra value as shown below + +```yaml +-e btrix_db_url: (contents of /tmp/YYYY-MM-DD@:HH:MMd_ocean_btrix_db_url.txt` +-e lb_uuid: (contents of /tmp/YYYY-MM-DD@:HH:MMd_ocean_lb_uuid.txt` +-e loadbalancer_ip: (contents of /tmp/YYYY-MM-DD@:HH:MMd_ocean_loadbalancer_ip.txt` +-e domain_name: - + doctl kubernetes cluster create {{ k8s_name }} --1-clicks ingress-nginx,cert-manager --node-pool + "{{ node_pools|join(',') }}" + --region={{ droplet_region }} + + async: 1800 + poll: 60 + changed_when: false + when: cluster_check.stdout.find(k8s_name) == -1 + + - name: d_ocean | k8s | Get information about our cluster + community.digitalocean.digital_ocean_kubernetes_info: + oauth_token: "{{ lookup('ansible.builtin.env', 'DO_API_TOKEN') }}" + name: "{{ k8s_name }}" + return_kubeconfig: true + register: my_cluster + + - name: d_ocean | k8s | print information about an existing DigitalOcean Kubernetes cluster + ansible.builtin.debug: + msg: Cluster name is {{ my_cluster.data.name }}, ID is {{ my_cluster.data.id }} + failed_when: not my_cluster + + - name: d_ocean | k8s | save kubectl config to kube_dir + ansible.builtin.command: doctl kubernetes cluster kubeconfig save {{ my_cluster.data.id }} + changed_when: false + + - name: d_ocean | k8s | get loadbalancer info from doctl + ansible.builtin.command: doctl k8s cluster list-associated-resources {{ my_cluster.data.id }} --format LoadBalancers --output json + register: lb_id_result + retries: 100 + delay: 5 + changed_when: lb_id_result.stdout | from_json | json_query('load_balancers') | length > 0 + until: lb_id_result.stdout | from_json | json_query('load_balancers') | length > 0 + + - name: d_ocean | k8s | parse lb id + ansible.builtin.set_fact: + lb_id: "{{ lb_id_result.stdout | from_json | json_query('load_balancers[0].id') }}" + + # DNS + # =========================================== + - name: d_ocean | dns | grab loadbalancer ip using doctl + ansible.builtin.command: doctl compute load-balancer get --format IP "{{ lb_id }}" + register: loadbalancer_ip_result + retries: 100 + delay: 5 + changed_when: loadbalancer_ip_result.stdout_lines | length > 1 + until: loadbalancer_ip_result.stdout_lines | length > 1 + + - name: d_ocean | dns | parse ip + ansible.builtin.set_fact: + lb_ip: "{{ loadbalancer_ip_result.stdout_lines[1] }}" + + - name: d_ocean | dns | register the dns for browsertrix cloud + ansible.builtin.command: >- + doctl compute domain records create --record-type A --record-name "{{ subdomain if subdomain else '@' }}" --record-data "{{ lb_ip }}" "{{ domain }}" + + changed_when: dns_result.rc == 0 + register: dns_result + + + # Signing + DNS + # =========================================== + - name: d_coean | signing | set signing domain + authtoken + ansible.builtin.set_fact: + full_signing_domain: "{{ signing_host }}.{{ full_domain }}" + signing_subdomain: "{{ signing_host + '.' + subdomain if subdomain else signing_host }}" + signing_authtoken: "{{ 99999999 | random | to_uuid }}" + + when: enable_signing + + - name: d_ocean | signing | register the dns for signing subdomain + ansible.builtin.command: >- + doctl compute domain records create --record-type A --record-name "{{ signing_subdomain }}" --record-data "{{ lb_ip }}" "{{ domain }}" + + register: signing_dns_result + when: enable_signing + + + # Registry + # =========================================== + - name: d_ocean | registry | get endpoint, if using registry + ansible.builtin.command: doctl registry get --format Endpoint + register: do_registry_result + when: use_do_registry + failed_when: do_registry_result.stdout_lines | length < 2 + + - name: d_ocean | registry | store registry endpoint + ansible.builtin.set_fact: + registry_endpoint: "{{ do_registry_result.stdout_lines[1] }}" + when: use_do_registry + + - name: d_ocean | registry | add to new k8s cluster + ansible.builtin.shell: set -o pipefail && doctl registry kubernetes-manifest | kubectl apply -f - + when: use_do_registry + + + # Helm Output + Deploy + # =========================================== + - name: d_ocean | helm | output values yaml + ansible.builtin.template: + src: ../group_vars/do/do-values.template.yaml + dest: ../deploys/{{ project_name }}-values.yaml + mode: u+rw + + - name: d_ocean | helm | deploy btrix + ansible.builtin.command: helm upgrade --install -f ../../chart/values.yaml -f ../deploys/{{ project_name }}-values.yaml btrix ../../chart/ + register: helm_result + changed_when: helm_result.rc == 0 + + tags: helm_upgrade diff --git a/chart/values.yaml b/chart/values.yaml index 61b80b75..c43e6ec0 100644 --- a/chart/values.yaml +++ b/chart/values.yaml @@ -12,7 +12,7 @@ volume_storage_class: # if set, set the node selector 'nodeType' to this crawling pods # crawler_node_type: -registration_enabled: 0 +registration_enabled: "0" jwt_token_lifetime_minutes: 1440 # number of workers for backend api @@ -118,7 +118,7 @@ crawler_namespace: "crawlers" crawl_retries: 1000 # browsertrix-crawler args: -crawler_args: "--timeout 90 --logging stats,behaviors,debug --generateWACZ --text --workers 4 --collection thecrawl --screencastPort 9037 --sizeLimit 100000000000 --timeLimit 18000 --healthCheckPort 6065 --waitOnDone" +crawler_args: "--timeout 120 --logging stats,behaviors,debug --generateWACZ --text --workers 4 --collection thecrawl --screencastPort 9037 --sizeLimit 100000000000 --timeLimit 18000 --healthCheckPort 6065 --waitOnDone --behaviorTimeout 300" crawler_requests_cpu: "800m" crawler_limits_cpu: "1200m" @@ -199,9 +199,9 @@ ingress: # optionally enable signer signer: enabled: false + image: webrecorder/authsign:0.5.0 # host: # cert_email: "test@example.com - # image: webrecorder/authsign:0.4.0 # image_pull_policy: "IfNotPresent" # auth_token: