forked from cerc-io/testnet-ops
Compare commits
13 Commits
ag-nitro-b
...
main
Author | SHA1 | Date | |
---|---|---|---|
bd1c7bcb3f | |||
65be098ce9 | |||
2e0fbd82f1 | |||
f597e5dfc7 | |||
18df60a291 | |||
631a859080 | |||
40428cdaa3 | |||
bcbd175f00 | |||
cd314d2fdf | |||
23f3a4c8ed | |||
88e0b48540 | |||
e142357428 | |||
a7af33a45b |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
hosts.ini
|
56
README.md
56
README.md
@ -1,2 +1,58 @@
|
|||||||
# testnet-ops
|
# testnet-ops
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
- Install [Ansible](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-and-upgrading-ansible-with-pip)
|
||||||
|
|
||||||
|
- Add location of the directory containing the ansible binary to your `PATH`
|
||||||
|
|
||||||
|
- Set Locale Encoding to `UTF-8`
|
||||||
|
|
||||||
|
Ansible requires the locale encoding to be `UTF-8`. You can either use the `LANG` prefix when running Ansible commands or set the system-wide locale
|
||||||
|
|
||||||
|
- Option 1: Use `LANG` Prefix in Commands
|
||||||
|
|
||||||
|
If you prefer not to change the system-wide locale, you can use the `LANG` prefix when running Ansible commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.UTF-8 ansible-playbook your_playbook.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Option 2: Set System-Wide Locale
|
||||||
|
|
||||||
|
- Edit the `/etc/default/locale` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nano /etc/default/locale
|
||||||
|
```
|
||||||
|
|
||||||
|
- Set the `LANG` variable to en_US.UTF-8:
|
||||||
|
|
||||||
|
```
|
||||||
|
LANG="en_US.UTF-8"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Reboot your system or log out and log back in to apply the changes
|
||||||
|
|
||||||
|
- Reference: <https://udhayakumarc.medium.com/error-ansible-requires-the-locale-encoding-to-be-utf-8-detected-iso8859-1-6da808387f7d>
|
||||||
|
|
||||||
|
- Verify ansible installation by running the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible --version
|
||||||
|
# ansible [core 2.17.2]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Install `sshpass` used for automating SSH password authentication
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt-get install sshpass
|
||||||
|
```
|
||||||
|
|
||||||
|
## Playbooks
|
||||||
|
|
||||||
|
- [stack-orchestrator-setup](./stack-orchestrator-setup/README.md)
|
||||||
|
- [nitro-node-setup](./nitro-nodes-setup/README.md)
|
||||||
|
- [nitro-bridge-setup](./nitro-bridge-setup/README.md)
|
||||||
|
- [nitro-contracts-setup](./nitro-contracts-setup/README.md)
|
||||||
|
- [service-provider-setup](./service-provider-setup/README.md)
|
||||||
|
2
hosts.example.ini
Normal file
2
hosts.example.ini
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
[deployment_host]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
3
nitro-bridge-setup/.gitignore
vendored
Normal file
3
nitro-bridge-setup/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
out
|
||||||
|
bridge-vars.yml
|
||||||
|
hosts.ini
|
102
nitro-bridge-setup/README.md
Normal file
102
nitro-bridge-setup/README.md
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# nitro-bridge-setup
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: To get started, follow the [installation](../README.md#installation) guide to setup ansible on your machine.
|
||||||
|
|
||||||
|
- Setup user with passwordless sudo: Follow steps from [Setup a user](../user-setup/README.md#setup-a-user) to setup a new user
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The following commands have to be executed in the [`nitro-bridge-setup`](./) directory:
|
||||||
|
|
||||||
|
- Copy the `bridge-vars.example.yml` vars file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp bridge-vars.example.yml bridge-vars.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit [`bridge-vars.yml`](./bridge-vars.yml) with the required values:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# L1 WS endpoint
|
||||||
|
nitro_chain_url: ""
|
||||||
|
|
||||||
|
# Private key for the bridge's nitro address
|
||||||
|
nitro_sc_pk: ""
|
||||||
|
|
||||||
|
# Private key for a funded account on L1
|
||||||
|
# This account should have tokens for funding Nitro channels
|
||||||
|
nitro_chain_pk: ""
|
||||||
|
|
||||||
|
# Custom L2 token to be deployed
|
||||||
|
token_name: "LaconicNetworkToken"
|
||||||
|
token_symbol: "LNT"
|
||||||
|
initial_token_supply: "129600"
|
||||||
|
|
||||||
|
# Addresses of the deployed nitro contracts
|
||||||
|
na_address: ""
|
||||||
|
vpa_address: ""
|
||||||
|
ca_address: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run Nitro Bridge
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[<deployment_host>]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<deployment_host>` with `nitro_host`
|
||||||
|
- Replace `<host_name>` with the alias of your choice
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Replace `<ssh_user>` with the username of the user that you set up on target machine (e.g. dev, ubuntu)
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Execute the `run-nitro-bridge.yml` Ansible playbook for deploying nitro bridge:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini run-nitro-bridge.yml --extra-vars='{ "target_host": "nitro_host"}' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: By default, deployments are created in an `out` directory. To change this location, update the `nitro_directory` variable in the [setup-vars.yml](./setup-vars.yml) file
|
||||||
|
|
||||||
|
- For skipping container build, run with `"skip_container_build" : true` in the `--extra-vars` parameter:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini run-nitro-bridge.yml --extra-vars='{ "target_host": "nitro_host", "skip_container_build": true }' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Check Deployment Status
|
||||||
|
|
||||||
|
Run the following command in the directory where the bridge-deployment is created:
|
||||||
|
|
||||||
|
- Check logs for deployments:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check the bridge deployment logs, ensure that the node is running
|
||||||
|
laconic-so deployment --dir bridge-deployment logs nitro-bridge -f
|
||||||
|
```
|
6
nitro-bridge-setup/bridge-vars.example.yml
Normal file
6
nitro-bridge-setup/bridge-vars.example.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
nitro_chain_url: ""
|
||||||
|
nitro_chain_pk: ""
|
||||||
|
nitro_sc_pk: ""
|
||||||
|
na_address: ""
|
||||||
|
vpa_address: ""
|
||||||
|
ca_address: ""
|
57
nitro-bridge-setup/run-nitro-bridge.yml
Normal file
57
nitro-bridge-setup/run-nitro-bridge.yml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
- name: Setup go-nitro on host
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- setup-vars.yml
|
||||||
|
- bridge-vars.yml
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create directory for nitro bridge deployment
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Change owner of nitro-directory
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
owner: "{{ansible_user}}"
|
||||||
|
group: "{{ansible_user}}"
|
||||||
|
state: directory
|
||||||
|
recurse: yes
|
||||||
|
|
||||||
|
- name: Clone go-nitro stack repo
|
||||||
|
expect:
|
||||||
|
command: laconic-so fetch-stack git.vdb.to/cerc-io/nitro-stack --git-ssh --pull
|
||||||
|
responses:
|
||||||
|
"Are you sure you want to continue connecting \\(yes/no/\\[fingerprint\\]\\)\\?": "yes"
|
||||||
|
timeout: 300
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Build containers
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/bridge build-containers --force-rebuild
|
||||||
|
when: not skip_container_build
|
||||||
|
|
||||||
|
- name: Check if deployment exists for bridge node
|
||||||
|
stat:
|
||||||
|
path: "{{ nitro_directory }}/bridge-deployment"
|
||||||
|
register: bridge_deployment
|
||||||
|
|
||||||
|
- name: Generate spec file for bridge deployment
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/bridge-nitro-spec.yml.j2"
|
||||||
|
dest: "{{ nitro_directory }}/bridge-nitro-spec.yml"
|
||||||
|
when: not bridge_deployment.stat.exists
|
||||||
|
|
||||||
|
- name: Create a deployment for the bridge node
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/bridge deploy create --spec-file bridge-nitro-spec.yml --deployment-dir bridge-deployment
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
when: not bridge_deployment.stat.exists
|
||||||
|
|
||||||
|
- name: Start the nitro bridge
|
||||||
|
command: laconic-so deployment --dir bridge-deployment start
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
3
nitro-bridge-setup/setup-vars.yml
Normal file
3
nitro-bridge-setup/setup-vars.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target_host: "nitro_host"
|
||||||
|
nitro_directory: out
|
||||||
|
skip_container_build: false
|
20
nitro-bridge-setup/templates/specs/bridge-nitro-spec.yml.j2
Normal file
20
nitro-bridge-setup/templates/specs/bridge-nitro-spec.yml.j2
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
stack: /home/{{ ansible_user }}/cerc/nitro-stack/stack-orchestrator/stacks/bridge
|
||||||
|
deploy-to: compose
|
||||||
|
config:
|
||||||
|
NITRO_CHAIN_URL: {{ nitro_chain_url }}
|
||||||
|
NITRO_CHAIN_PK: {{ nitro_chain_pk }}
|
||||||
|
NITRO_SC_PK: {{ nitro_sc_pk }}
|
||||||
|
NA_ADDRESS: "{{ na_address }}"
|
||||||
|
VPA_ADDRESS: "{{ vpa_address }}"
|
||||||
|
CA_ADDRESS: "{{ ca_address }}"
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
nitro-bridge:
|
||||||
|
- 0.0.0.0:3005:3005
|
||||||
|
- 0.0.0.0:3006:3006
|
||||||
|
- 0.0.0.0:4006:4006
|
||||||
|
volumes:
|
||||||
|
nitro_bridge_data: ./data/nitro_bridge_data
|
||||||
|
nitro_bridge_tls: ./data/nitro_bridge_tls
|
||||||
|
nitro_node_caroot: ./data/nitro_node_caroot
|
||||||
|
nitro_deployment: ./data/nitro_deployment
|
3
nitro-contracts-setup/.gitignore
vendored
Normal file
3
nitro-contracts-setup/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
out
|
||||||
|
contract-vars.yml
|
||||||
|
hosts.ini
|
106
nitro-contracts-setup/README.md
Normal file
106
nitro-contracts-setup/README.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# nitro-contracts-setup
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: To get started, follow the [installation](../README.md#installation) guide to setup ansible on your machine.
|
||||||
|
|
||||||
|
- Setup user with passwordless sudo: Follow steps from [Setup a user](../user-setup/README.md#setup-a-user) to setup a new user with passwordless sudo
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The following commands have to be executed in the [`nitro-contracts-setup`](./) directory:
|
||||||
|
|
||||||
|
- Copy the `contract-vars.example.yml` vars file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp contract-vars.example.yml contract-vars.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit [`contract-vars.yml`](./contract-vars.yml) and fill in the following values
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# L1 RPC endpoint
|
||||||
|
geth_url: ""
|
||||||
|
|
||||||
|
# L1 chain ID
|
||||||
|
geth_chain_id: ""
|
||||||
|
|
||||||
|
# Private key for a funded account on L1 to use for contracts deployment on L1
|
||||||
|
geth_deployer_pk: ""
|
||||||
|
|
||||||
|
# Custom L1 token to be deployed
|
||||||
|
token_name: "TestToken"
|
||||||
|
token_symbol: "TST"
|
||||||
|
initial_token_supply: "129600"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploy Contracts
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[<deployment_host>]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<deployment_host>` with `nitro_host`
|
||||||
|
- Replace `<host_name>` with the alias of your choice
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Replace `<ssh_user>` with the username of the user that you set up on target machine (e.g. dev, ubuntu)
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Execute the `deploy-contracts.yml` Ansible playbook to deploy nitro contracts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini deploy-contracts.yml --extra-vars='{ "target_host": "nitro_host"}' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: By default, deployments are created in an `out` directory. To change this location, update the `nitro_directory` variable in the [setup-vars.yml](./setup-vars.yml) file
|
||||||
|
|
||||||
|
- For skipping container build, run with `"skip_container_build" : true` in the `--extra-vars` parameter:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini deploy-contracts.yml --extra-vars='{ "target_host": "nitro_host", "skip_container_build": true }' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Check Deployment Status
|
||||||
|
|
||||||
|
Run the following command in the directory where the nitro-contracts-deployment is created:
|
||||||
|
|
||||||
|
- Check logs for deployments:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check the L2 nitro contract deployment logs
|
||||||
|
laconic-so deployment --dir nitro-contracts-deployment logs l2-nitro-contracts -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## Get Contract Addresses
|
||||||
|
|
||||||
|
Run the following commands in the directory where the deployments are created:
|
||||||
|
|
||||||
|
- Get addresses of L1 nitro contracts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so deployment --dir nitro-contracts-deployment exec nitro-contracts "cat /app/deployment/nitro-addresses.json"
|
||||||
|
```
|
6
nitro-contracts-setup/contract-vars.example.yml
Normal file
6
nitro-contracts-setup/contract-vars.example.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
geth_url: ""
|
||||||
|
geth_chain_id: ""
|
||||||
|
geth_deployer_pk: ""
|
||||||
|
token_name: ""
|
||||||
|
token_symbol: ""
|
||||||
|
initial_token_supply: ""
|
101
nitro-contracts-setup/deploy-contracts.yml
Normal file
101
nitro-contracts-setup/deploy-contracts.yml
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
- name: Deploy nitro contracts
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- setup-vars.yml
|
||||||
|
- contract-vars.yml
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create directory for nitro bridge deployment
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Change owner of nitro-directory
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
owner: "{{ansible_user}}"
|
||||||
|
group: "{{ansible_user}}"
|
||||||
|
state: directory
|
||||||
|
recurse: yes
|
||||||
|
|
||||||
|
- name: Clone nitro stack repo
|
||||||
|
expect:
|
||||||
|
command: laconic-so fetch-stack git.vdb.to/cerc-io/nitro-stack --git-ssh --pull
|
||||||
|
responses:
|
||||||
|
"Are you sure you want to continue connecting \\(yes/no/\\[fingerprint\\]\\)\\?": "yes"
|
||||||
|
timeout: 300
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Clone repositories required for nitro-stack
|
||||||
|
expect:
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-contracts setup-repositories --git-ssh --pull
|
||||||
|
responses:
|
||||||
|
"Are you sure you want to continue connecting \\(yes/no/\\[fingerprint\\]\\)\\?": "yes"
|
||||||
|
timeout: 300
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Build containers
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-contracts build-containers --force-rebuild
|
||||||
|
when: not skip_container_build
|
||||||
|
|
||||||
|
- name: Generate spec file for nitro contracts deployment
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/nitro-contracts-spec.yml.j2"
|
||||||
|
dest: "{{ nitro_directory }}/nitro-contracts-spec.yml"
|
||||||
|
|
||||||
|
- name: Check if deployment exists for nitro contracts
|
||||||
|
stat:
|
||||||
|
path: "{{ nitro_directory }}/nitro-contracts-deployment"
|
||||||
|
register: nitro_contracts_deployment
|
||||||
|
|
||||||
|
- name: Create a deployment for nitro contracts
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-contracts deploy create --spec-file nitro-contracts-spec.yml --deployment-dir nitro-contracts-deployment
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
when: not nitro_contracts_deployment.stat.exists
|
||||||
|
|
||||||
|
- name: Start deployment for nitro-contracts
|
||||||
|
command: laconic-so deployment --dir nitro-contracts-deployment start
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
|
||||||
|
- name: Wait for the contracts to be deployed
|
||||||
|
wait_for:
|
||||||
|
path: "{{ nitro_directory }}/nitro-contracts-deployment/data/nitro_deployment/nitro-addresses.json"
|
||||||
|
timeout: 300
|
||||||
|
|
||||||
|
- name: Export NA_ADDRESS
|
||||||
|
shell: laconic-so deployment --dir nitro-contracts-deployment exec nitro-contracts "jq -r '.\"{{ geth_chain_id }}\"[0].contracts.NitroAdjudicator.address' /app/deployment/nitro-addresses.json"
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
register: na_address
|
||||||
|
- debug:
|
||||||
|
msg: "NA_ADDRESS: {{ na_address.stdout }}"
|
||||||
|
|
||||||
|
- name: Export CA_ADDRESS
|
||||||
|
shell: laconic-so deployment --dir nitro-contracts-deployment exec nitro-contracts "jq -r '.\"{{ geth_chain_id }}\"[0].contracts.ConsensusApp.address' /app/deployment/nitro-addresses.json"
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
register: ca_address
|
||||||
|
- debug:
|
||||||
|
msg: "CA_ADDRESS: {{ ca_address.stdout }}"
|
||||||
|
|
||||||
|
- name: Export VPA_ADDRESS
|
||||||
|
shell: laconic-so deployment --dir nitro-contracts-deployment exec nitro-contracts "jq -r '.\"{{ geth_chain_id }}\"[0].contracts.VirtualPaymentApp.address' /app/deployment/nitro-addresses.json"
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
register: vpa_address
|
||||||
|
- debug:
|
||||||
|
msg: "VPA_ADDRESS: {{ vpa_address.stdout }}"
|
||||||
|
|
||||||
|
- name: Export ASSET_ADDRESS
|
||||||
|
shell: laconic-so deployment --dir nitro-contracts-deployment exec nitro-contracts "jq -r '.\"{{ geth_chain_id }}\"[0].contracts.{{ token_name }}.address' /app/deployment/nitro-addresses.json"
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
register: asset_address
|
||||||
|
- debug:
|
||||||
|
msg: "ASSET_ADDRESS: {{ asset_address.stdout }}"
|
3
nitro-contracts-setup/setup-vars.yml
Normal file
3
nitro-contracts-setup/setup-vars.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target_host: "nitro_host"
|
||||||
|
nitro_directory: out
|
||||||
|
skip_container_build: false
|
@ -0,0 +1,13 @@
|
|||||||
|
stack: /home/{{ ansible_user }}/cerc/nitro-stack/stack-orchestrator/stacks/nitro-contracts
|
||||||
|
deploy-to: compose
|
||||||
|
config:
|
||||||
|
GETH_URL: {{ geth_url }}
|
||||||
|
GETH_CHAIN_ID: {{ geth_chain_id }}
|
||||||
|
GETH_DEPLOYER_PK: {{ geth_deployer_pk }}
|
||||||
|
TOKEN_NAME: {{ token_name }}
|
||||||
|
TOKEN_SYMBOL: {{ token_symbol }}
|
||||||
|
INITIAL_TOKEN_SUPPLY: {{ initial_token_supply }}
|
||||||
|
network:
|
||||||
|
ports: {}
|
||||||
|
volumes:
|
||||||
|
nitro_deployment: ./data/nitro_deployment
|
3
nitro-nodes-setup/.gitignore
vendored
Normal file
3
nitro-nodes-setup/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
out
|
||||||
|
nitro-vars.yml
|
||||||
|
hosts.ini
|
121
nitro-nodes-setup/README.md
Normal file
121
nitro-nodes-setup/README.md
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
# nitro-nodes-setup
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: To get started, follow the [installation](../README.md#installation) guide to setup ansible on your machine.
|
||||||
|
|
||||||
|
- Setup user with passwordless sudo: Follow steps from [Setup a user](../user-setup/README.md#setup-a-user) to setup a new user with passwordless sudo
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
The following commands have to be executed in [`nitro-nodes-setup`](./) directory
|
||||||
|
|
||||||
|
- Copy the `nitro-vars.example.yml` vars file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp nitro-vars.example.yml nitro-vars.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit [`nitro-vars.yml`](./nitro-vars.yml) and fill in the following values
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# L1 WS endpoint
|
||||||
|
nitro_chain_url: ""
|
||||||
|
|
||||||
|
# Private key for your nitro address
|
||||||
|
nitro_sc_pk: ""
|
||||||
|
|
||||||
|
# Private key of the account on chain that is used for funding channels in Nitro node
|
||||||
|
nitro_chain_pk: ""
|
||||||
|
|
||||||
|
# Contract address of NitroAdjudicator
|
||||||
|
na_address: ""
|
||||||
|
|
||||||
|
# Contract address of VirtualPaymentApp
|
||||||
|
vpa_address: ""
|
||||||
|
|
||||||
|
# Contract address of ConsensusApp
|
||||||
|
ca_address: ""
|
||||||
|
|
||||||
|
# Multiaddr of the L1 bridge node
|
||||||
|
nitro_l1_bridge_multiaddr: ""
|
||||||
|
|
||||||
|
# Multiaddr of the L2 bridge node
|
||||||
|
nitro_l2_bridge_multiaddr: ""
|
||||||
|
|
||||||
|
# Multiaddr with publically accessible IP address / DNS for your L1 nitro node
|
||||||
|
# Example: "/ip4/192.168.x.y/tcp/3009"
|
||||||
|
# Example: "/dns4/example.com/tcp/3009"
|
||||||
|
nitro_l1_ext_multiaddr: ""
|
||||||
|
|
||||||
|
# Multiaddr with publically accessible IP address / DNS for your L2 nitro node
|
||||||
|
nitro_l2_ext_multiaddr: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
## Run Nitro Node
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[<deployment_host>]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<deployment_host>` with `nitro_host`
|
||||||
|
- Replace `<host_name>` with the alias of your choice
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Replace `<ssh_user>` with the username of the user that you set up on target machine (e.g. dev, ubuntu)
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Copy and edit the [`nitro-vars.yml`](./nitro-vars.yml) file as described in the [local setup](./README.md#run-nitro-node-on-local-host) section
|
||||||
|
|
||||||
|
- Execute the `run-nitro-nodes.yml` Ansible playbook to deploy nitro nodes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini run-nitro-nodes.yml --extra-vars='{ "target_host": "nitro_host"}' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: By default, deployments are created in a `out` directory. To change this location, update the `nitro_directory` variable in the [setup-vars.yml](./setup-vars.yml) file
|
||||||
|
|
||||||
|
- For skipping container build, run with `"skip_container_build" : true` in the `--extra-vars` parameter:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook -i hosts.ini run-nitro-nodes.yml --extra-vars='{ "target_host": "nitro_host", "skip_container_build": true }' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Check Deployment Status
|
||||||
|
|
||||||
|
Run the following command in the directory where the deployments are created
|
||||||
|
|
||||||
|
- Check L1 nitro node logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so deployment --dir l1-nitro-deployment logs nitro-node -f
|
||||||
|
```
|
||||||
|
|
||||||
|
- Check L2 nitro node logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
laconic-so deployment --dir l2-nitro-deployment logs nitro-node -f
|
||||||
|
```
|
10
nitro-nodes-setup/nitro-vars.example.yml
Normal file
10
nitro-nodes-setup/nitro-vars.example.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
nitro_chain_url: ""
|
||||||
|
nitro_sc_pk: ""
|
||||||
|
nitro_chain_pk: ""
|
||||||
|
na_address: ""
|
||||||
|
vpa_address: ""
|
||||||
|
ca_address: ""
|
||||||
|
nitro_l1_bridge_multiaddr: ""
|
||||||
|
nitro_l2_bridge_multiaddr: ""
|
||||||
|
nitro_l1_ext_multiaddr: ""
|
||||||
|
nitro_l2_ext_multiaddr: ""
|
122
nitro-nodes-setup/run-nitro-nodes.yml
Normal file
122
nitro-nodes-setup/run-nitro-nodes.yml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
- name: Setup and run nitro nodes
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- setup-vars.yml
|
||||||
|
- nitro-vars.yml
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install yq
|
||||||
|
get_url:
|
||||||
|
url: https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
|
||||||
|
dest: /usr/bin/yq
|
||||||
|
mode: '0755'
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Create directory for nitro-stack
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Change owner of nitro-directory
|
||||||
|
file:
|
||||||
|
path: "{{ nitro_directory }}"
|
||||||
|
owner: "{{ansible_user}}"
|
||||||
|
group: "{{ansible_user}}"
|
||||||
|
state: directory
|
||||||
|
recurse: yes
|
||||||
|
|
||||||
|
- name: Clone nitro-stack repo
|
||||||
|
expect:
|
||||||
|
command: laconic-so fetch-stack git.vdb.to/cerc-io/nitro-stack --git-ssh --pull
|
||||||
|
responses:
|
||||||
|
"Are you sure you want to continue connecting \\(yes/no/\\[fingerprint\\]\\)\\?": "yes"
|
||||||
|
timeout: 300
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Build containers
|
||||||
|
command: laconic-so --stack {{ ansible_env.HOME }}/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node build-containers --force-rebuild
|
||||||
|
when: not skip_container_build
|
||||||
|
|
||||||
|
- name: Generate spec file for L1 nitro node
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/l1-nitro-spec.yml.j2"
|
||||||
|
dest: "{{ nitro_directory }}/l1-nitro-spec.yml"
|
||||||
|
|
||||||
|
- name: Generate spec file for L2 nitro node
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/l2-nitro-spec.yml.j2"
|
||||||
|
dest: "{{ nitro_directory }}/l2-nitro-spec.yml"
|
||||||
|
|
||||||
|
- name: Check if deployment exists for L1 nitro node
|
||||||
|
stat:
|
||||||
|
path: "{{ nitro_directory }}/l1-nitro-deployment"
|
||||||
|
register: l1_deployment
|
||||||
|
|
||||||
|
- name: Create a deployment for L1 nitro node
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l1-nitro-spec.yml --deployment-dir l1-nitro-deployment
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
when: not l1_deployment.stat.exists
|
||||||
|
|
||||||
|
- name: Check if deployment exists for L2 nitro node
|
||||||
|
stat:
|
||||||
|
path: "{{ nitro_directory }}/l2-nitro-deployment"
|
||||||
|
register: l2_deployment
|
||||||
|
|
||||||
|
- name: Create a deployment for L2 nitro node
|
||||||
|
command: laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l2-nitro-spec.yml --deployment-dir l2-nitro-deployment
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
when: not l2_deployment.stat.exists
|
||||||
|
|
||||||
|
- name: Check if the config.env file is empty for L1 deployment
|
||||||
|
shell: "[ -s {{ nitro_directory }}/l1-nitro-deployment/config.env ] && echo 'File is not empty' || echo 'File is empty'"
|
||||||
|
register: file_check_result
|
||||||
|
|
||||||
|
- name: Display the result of the file check
|
||||||
|
debug:
|
||||||
|
msg: "{{ file_check_result.stdout }}"
|
||||||
|
|
||||||
|
- name: Copy config.env for L1 nitro deployment if it is empty
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/l1-nitro-config.env.j2"
|
||||||
|
dest: "{{ nitro_directory }}/l1-nitro-deployment/config.env"
|
||||||
|
when: file_check_result.stdout == 'File is empty'
|
||||||
|
|
||||||
|
- name: Check if the config.env file is empty for L2 deployment
|
||||||
|
shell: "[ -s {{ nitro_directory }}/l2-nitro-deployment/config.env ] && echo 'File is not empty' || echo 'File is empty'"
|
||||||
|
register: file_check_result
|
||||||
|
|
||||||
|
- name: Display the result of the file check
|
||||||
|
debug:
|
||||||
|
msg: "{{ file_check_result.stdout }}"
|
||||||
|
|
||||||
|
- name: Copy config.env for L2 nitro deployment if it is empty
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/l2-nitro-config.env.j2"
|
||||||
|
dest: "{{ nitro_directory }}/l2-nitro-deployment/config.env"
|
||||||
|
when: file_check_result.stdout == 'File is empty'
|
||||||
|
|
||||||
|
- name: Start deployment for L1 nitro node
|
||||||
|
command: laconic-so deployment --dir l1-nitro-deployment start
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
|
||||||
|
- name: Start deployment for L2 nitro node
|
||||||
|
command: laconic-so deployment --dir l2-nitro-deployment start
|
||||||
|
args:
|
||||||
|
chdir: "{{ nitro_directory }}"
|
||||||
|
|
||||||
|
- name: Fetch the nitro-node-config file
|
||||||
|
get_url:
|
||||||
|
url: https://git.vdb.to/cerc-io/testnet-laconicd-stack/raw/branch/main/ops/stage2/nitro-node-config.yml
|
||||||
|
dest: "{{ nitro_directory }}"
|
||||||
|
|
||||||
|
- name: Fetch required asset addresses
|
||||||
|
get_url:
|
||||||
|
url: https://git.vdb.to/cerc-io/testnet-laconicd-stack/raw/branch/main/ops/stage2/assets.json
|
||||||
|
dest: "{{ nitro_directory }}"
|
3
nitro-nodes-setup/setup-vars.yml
Normal file
3
nitro-nodes-setup/setup-vars.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
target_host: "nitro_host"
|
||||||
|
nitro_directory: out
|
||||||
|
skip_container_build: false
|
@ -0,0 +1,8 @@
|
|||||||
|
NITRO_CHAIN_URL={{ nitro_chain_url }}
|
||||||
|
NITRO_SC_PK={{ nitro_sc_pk }}
|
||||||
|
NITRO_CHAIN_PK={{ nitro_chain_pk }}
|
||||||
|
NA_ADDRESS="{{ na_address }}"
|
||||||
|
VPA_ADDRESS="{{ vpa_address }}"
|
||||||
|
CA_ADDRESS="{{ ca_address }}"
|
||||||
|
NITRO_BOOTPEERS={{ nitro_l1_bridge_multiaddr }}
|
||||||
|
NITRO_EXT_MULTIADDR={{ nitro_l1_ext_multiaddr }}
|
@ -0,0 +1,6 @@
|
|||||||
|
NITRO_SC_PK={{ nitro_sc_pk }}
|
||||||
|
VPA_ADDRESS="{{ vpa_address }}"
|
||||||
|
CA_ADDRESS="{{ ca_address }}"
|
||||||
|
NITRO_BOOTPEERS={{ nitro_l2_bridge_multiaddr }}
|
||||||
|
NITRO_EXT_MULTIADDR={{ nitro_l2_ext_multiaddr }}
|
||||||
|
NITRO_L2=true
|
11
nitro-nodes-setup/templates/specs/l1-nitro-spec.yml.j2
Normal file
11
nitro-nodes-setup/templates/specs/l1-nitro-spec.yml.j2
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
stack: /home/{{ansible_user}}/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node
|
||||||
|
deploy-to: compose
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
nitro-node:
|
||||||
|
- 3007:3005
|
||||||
|
- 4007:4005
|
||||||
|
volumes:
|
||||||
|
nitro_node_data: ./data/nitro_node_data
|
||||||
|
nitro_node_tls: ./data/nitro_node_tls
|
||||||
|
nitro_node_caroot: ./data/nitro_node_caroot
|
11
nitro-nodes-setup/templates/specs/l2-nitro-spec.yml.j2
Normal file
11
nitro-nodes-setup/templates/specs/l2-nitro-spec.yml.j2
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
stack: /home/{{ansible_user}}/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node
|
||||||
|
deploy-to: compose
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
nitro-node:
|
||||||
|
- 3009:3005
|
||||||
|
- 4009:4005
|
||||||
|
volumes:
|
||||||
|
nitro_node_data: ./data/nitro_node_data
|
||||||
|
nitro_node_tls: ./data/nitro_node_tls
|
||||||
|
nitro_node_caroot: ./data/nitro_node_caroot
|
2
service-provider-setup/.gitignore
vendored
Normal file
2
service-provider-setup/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
vars/*.yml
|
||||||
|
!vars/*.example.yml
|
201
service-provider-setup/README.md
Normal file
201
service-provider-setup/README.md
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# service-provider-setup
|
||||||
|
|
||||||
|
This setup has been tested on digitalocean droplets running ubuntu 22.04 LTS
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: follow the [installation](../README.md#installation) guide to setup ansible on your machine
|
||||||
|
|
||||||
|
- Set up a DigitalOcean Droplet with passwordless SSH access
|
||||||
|
|
||||||
|
- Buy a domain and configure [nameservers pointing to DigitalOcean](https://docs.digitalocean.com/products/networking/dns/getting-started/dns-registrars/)
|
||||||
|
|
||||||
|
- Generate a DigitalOcean access token, used for API authentication and managing cloud resources
|
||||||
|
|
||||||
|
- Setup a user: Follow steps from [Setup a user](../user-setup/README.md#setup-a-user) to setup a new user with passwordless sudo
|
||||||
|
|
||||||
|
## Become a Service Provider
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
- Copy the vars files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd vars
|
||||||
|
cp dns-vars.example.yml dns-vars.yml
|
||||||
|
cp gpg-vars.example.yml gpg-vars.yml
|
||||||
|
cp k8s-vars.example.yml k8s-vars.yml
|
||||||
|
cp container-vars.example.yml container-vars.yml
|
||||||
|
cp laconicd-vars.example.yml laconicd-vars.yml
|
||||||
|
cp webapp-vars.example.yml webapp-vars.yml
|
||||||
|
cd -
|
||||||
|
```
|
||||||
|
|
||||||
|
- Update the following values in the respective variable files:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# vars/dns-vars.yml
|
||||||
|
full_domain: "" # eg: laconic.com
|
||||||
|
service_provider_ip: "" # eg: 23.111.78.179
|
||||||
|
do_api_token: "" # DigitalOcean access token that you generated, eg: dop_v1...
|
||||||
|
|
||||||
|
# vars/gpg-vars.yml
|
||||||
|
gpg_user_name: "" # full name of the user for the GPG key
|
||||||
|
gpg_user_email: "" # email address associated with the GPG key
|
||||||
|
gpg_passphrase: "" # passphrase for securing the GPG key
|
||||||
|
|
||||||
|
# vars/k8s-vars.yml
|
||||||
|
org_id: "" # eg: lcn
|
||||||
|
location_id: "" # eg: cad
|
||||||
|
support_email: "" # eg: support@laconic.com
|
||||||
|
|
||||||
|
# vars/container-vars.yml
|
||||||
|
container_registry_username: "" # username to login to the container registry
|
||||||
|
container_registry_password: "" # password to login to the container registry
|
||||||
|
|
||||||
|
# vars/laconicd-vars.yml
|
||||||
|
chain_id: "" # chain id to use for the Laconic chain
|
||||||
|
|
||||||
|
# vars/webapp-vars.yml
|
||||||
|
authority_name: "" # eg: laconic-authority
|
||||||
|
cpu_reservation: "1" # minimum number of cpu cores to be used, eg: 1
|
||||||
|
memory_reservation: "2G" # minimum amount of memory in GB to be used, eg: 2G
|
||||||
|
cpu_limit: "6" # maximum number of cpu cores to be used, eg: 6
|
||||||
|
memory_limit: "8G" # maximum amount of memory in GB to be used, eg: 8G
|
||||||
|
deployer_gpg_passphrase: "" # passphrase for creating GPG key used by webapp-deployer, eg: SECRET
|
||||||
|
handle_auction_requests: "true" # whether the webapp deployer should handle deployment auction requests, eg: true
|
||||||
|
auction_bid_amount: "500000" # bid amount for deployment auctions in alnt, eg: 500000
|
||||||
|
```
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[deployment_host]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<new_username> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<host_name>` with the desired `hostname` of the remote machine
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Under `deployment_host`, Replace `<ansible_user>` with the name of the user you have created
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Run the `service-provider-setup.yml` ansible-playbook to:
|
||||||
|
- Create DNS records
|
||||||
|
- Deploy k8s
|
||||||
|
- Setup laconicd and laconic console
|
||||||
|
- Setup container registry
|
||||||
|
- Deploy the webapp-deployer API and webapp-deployer UI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook service-provider-setup.yml -i hosts.ini --extra-vars='{ target_host: "deployment_host" }' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
### Result
|
||||||
|
|
||||||
|
After the playbook finishes executing, the following services will be deployed (your setup should look similar to the example below):
|
||||||
|
|
||||||
|
- laconicd chain RPC endpoint: <http://lcn-daemon.laconic.com:26657>
|
||||||
|
- laconicd GQL endpoint: <http://lcn-daemon.laconic.com:9473/api>
|
||||||
|
- laconic console: <http://lcn-console.laconic.com:8080/registry>
|
||||||
|
- webapp deployer API: <https://webapp-deployer-api.pwa.laconic.com>
|
||||||
|
- webapp deployer UI: <https://webapp-deployer-ui.pwa.laconic.com>
|
||||||
|
|
||||||
|
## Cleanup
|
||||||
|
|
||||||
|
Run the following steps on the target machine to stop the webapp-deployer, container-registry, fixturenet-laconicd and laconic-console-deployment, undeploy k8s, remove GPG keys and DNS records
|
||||||
|
- Stop deployments
|
||||||
|
|
||||||
|
```
|
||||||
|
$ laconic-so deployment --dir webapp-ui stop
|
||||||
|
$ laconic-so deployment --dir webapp-deployer
|
||||||
|
$ laconic-so deployment --dir container-registry stop
|
||||||
|
$ laconic-so deployment --dir laconic-console-deployment stop --delete-volumes
|
||||||
|
$ laconic-so deployment --dir fixturenet-laconicd-deployment stop --delete-volumes
|
||||||
|
```
|
||||||
|
|
||||||
|
- Remove deployment directories
|
||||||
|
```
|
||||||
|
sudo rm -rf webapp-ui
|
||||||
|
sudo rm -rf webapp-deployer
|
||||||
|
sudo rm -rf container-registry
|
||||||
|
sudo rm -rf laconic-console-deployment
|
||||||
|
sudo rm -rf fixturenet-laconicd-deployment
|
||||||
|
```
|
||||||
|
|
||||||
|
- Remove spec files
|
||||||
|
|
||||||
|
```
|
||||||
|
rm webapp-deployer.spec
|
||||||
|
rm container-registry.spec
|
||||||
|
rm laconic-console-spec.yml
|
||||||
|
rm fixturenet-laconicd-spec.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Undeploy the k8s
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cd service-provider-template
|
||||||
|
$ export VAULT_KEY=<gpg_passphrase>
|
||||||
|
$ bash .vault/vault-rekey.sh
|
||||||
|
$ ansible-playbook -i hosts site.yml --tags=k8s --limit=<org_id>_<location_id> --user <user> --extra-vars 'k8s_action=destroy'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Remove service-provider-template repo
|
||||||
|
```
|
||||||
|
$ rm -rf service-provider-template
|
||||||
|
```
|
||||||
|
|
||||||
|
- Remove any existing GPG keys
|
||||||
|
```
|
||||||
|
$ rm -rf gpg-keys/
|
||||||
|
$ gpg --list-secret-keys --keyid-format=long
|
||||||
|
/home/dev/.gnupg/pubring.kbx
|
||||||
|
----------------------------
|
||||||
|
sec rsa4096/DA9E3D638930A699 2024-10-15 [SCEA]
|
||||||
|
69A3200727091E72B773BBEBDA9E3D638930A699
|
||||||
|
uid [ultimate] deepstack <support@deepstacksoft.com>
|
||||||
|
ssb rsa3072/2B5D80CF44753EFD 2024-10-15 [SEA]
|
||||||
|
|
||||||
|
sec rsa3072/2449A62C838440AB 2024-10-15 [SC]
|
||||||
|
646A42164F978DC1415C11F12449A62C838440AB
|
||||||
|
uid [ultimate] webapp-deployer-api.deepstack.com
|
||||||
|
ssb rsa3072/67576558A2F2FE91 2024-10-15 [E]
|
||||||
|
|
||||||
|
$ gpg --delete-secret-key 69A3200727091E72B773BBEBDA9E3D638930A699
|
||||||
|
$ gpg --delete-key 69A3200727091E72B773BBEBDA9E3D638930A699
|
||||||
|
$ gpg --delete-secret-key 646A42164F978DC1415C11F12449A62C838440AB
|
||||||
|
$ gpg --delete-key 646A42164F978DC1415C11F12449A62C838440AB
|
||||||
|
```
|
||||||
|
- Remove the user if required
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ userdel <user>
|
||||||
|
|
||||||
|
# If required, kill process that is using the user
|
||||||
|
# userdel: user <user> is currently used by process 1639
|
||||||
|
# $ kill -9 1639
|
||||||
|
```
|
||||||
|
|
||||||
|
- Remove DNS records using DigitalOcean's API:
|
||||||
|
- <https://docs.digitalocean.com/reference/api/api-try-it-now/#/Domain%20Records/domains_delete_record>
|
128
service-provider-setup/deploy-backend.yml
Normal file
128
service-provider-setup/deploy-backend.yml
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
- name: Deploy webapp-deployer backend
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
KUBECONFIG: "{{ ansible_env.HOME }}/.kube/config-default.yaml"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/webapp-vars.yml
|
||||||
|
- vars/container-vars.yml
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/laconicd-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Ensure gpg-keys directory exists
|
||||||
|
file:
|
||||||
|
path: ~/gpg-keys
|
||||||
|
state: directory
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Create a GPG key
|
||||||
|
shell: gpg --batch --passphrase "{{ deployer_gpg_passphrase }}" --quick-generate-key webapp-deployer-api.{{ full_domain }} default default never
|
||||||
|
|
||||||
|
- name: Export the public key
|
||||||
|
shell: gpg --export webapp-deployer-api.{{ full_domain }} > ~/gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.pub
|
||||||
|
args:
|
||||||
|
creates: ~/gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.pub
|
||||||
|
|
||||||
|
- name: Export the GPG private key with passphrase
|
||||||
|
shell: gpg --pinentry-mode=loopback --passphrase "{{ deployer_gpg_passphrase }}" --export-secret-keys webapp-deployer-api.{{ full_domain }} > ~/gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.key
|
||||||
|
|
||||||
|
- name: Setup repositories for webapp-deployer-backend
|
||||||
|
command: laconic-so --stack webapp-deployer-backend setup-repositories
|
||||||
|
|
||||||
|
- name: Build containers for webapp-deployer-backend
|
||||||
|
command: laconic-so --stack webapp-deployer-backend build-containers
|
||||||
|
|
||||||
|
- name: Ensure the config directory exists
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/config"
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: Create laconic config file
|
||||||
|
template:
|
||||||
|
src: "./templates/laconic.yml.j2"
|
||||||
|
dest: "{{ ansible_env.HOME }}/config/laconic.yml"
|
||||||
|
|
||||||
|
- name: Copy the gpg private key file to config dir
|
||||||
|
copy:
|
||||||
|
src: "gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.key"
|
||||||
|
dest: "config"
|
||||||
|
remote_src: true
|
||||||
|
|
||||||
|
- name: Copy the gpg public key file to config dir
|
||||||
|
copy:
|
||||||
|
src: "gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.pub"
|
||||||
|
dest: "config"
|
||||||
|
remote_src: true
|
||||||
|
|
||||||
|
- name: Publish the webapp-deployer record using laconic-so
|
||||||
|
shell: |
|
||||||
|
docker run -i -t \
|
||||||
|
-v /home/{{ ansible_user }}/config:/home/root/config \
|
||||||
|
cerc/webapp-deployer-backend:local laconic-so publish-deployer-to-registry \
|
||||||
|
--laconic-config /home/root/config/laconic.yml \
|
||||||
|
--api-url https://webapp-deployer-api.pwa.{{ full_domain }} \
|
||||||
|
--public-key-file /home/root/config/webapp-deployer-api.{{ full_domain }}.pgp.pub \
|
||||||
|
--lrn lrn://{{ authority_name }}/deployers/webapp-deployer-api.pwa.{{ full_domain }} \
|
||||||
|
--min-required-payment 0
|
||||||
|
register: publish_output
|
||||||
|
|
||||||
|
- name: Display publish output
|
||||||
|
debug:
|
||||||
|
var: publish_output.stdout
|
||||||
|
|
||||||
|
- name: Generate spec file for webapp-deployer-backend
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/webapp-deployer.spec.j2"
|
||||||
|
dest: "webapp-deployer.spec"
|
||||||
|
|
||||||
|
- name: Create deployment directory for webapp-deployer
|
||||||
|
command: >
|
||||||
|
laconic-so --stack webapp-deployer-backend deploy create
|
||||||
|
--deployment-dir webapp-deployer --spec-file webapp-deployer.spec
|
||||||
|
|
||||||
|
- name: Update config for webapp-deployer-backend
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/webapp-deployer-config.env.j2"
|
||||||
|
dest: "webapp-deployer/config.env"
|
||||||
|
|
||||||
|
- name: Copy the kube config file to webapp-deployer directory
|
||||||
|
copy:
|
||||||
|
src: "{{ansible_env.HOME}}/.kube/config-default.yaml"
|
||||||
|
dest: "webapp-deployer/data/config/kube.yml"
|
||||||
|
remote_src: true
|
||||||
|
|
||||||
|
- name: Create laconic config file
|
||||||
|
template:
|
||||||
|
src: "./templates/laconic.yml.j2"
|
||||||
|
dest: "webapp-deployer/data/config/laconic.yml"
|
||||||
|
|
||||||
|
- name: login to the container registry
|
||||||
|
command: "docker login container-registry.pwa.{{ full_domain }} --username {{ container_registry_username }} --password {{ container_registry_password}}"
|
||||||
|
|
||||||
|
- name: Push images to container registry
|
||||||
|
command: laconic-so deployment --dir webapp-deployer push-images
|
||||||
|
|
||||||
|
- name: Start the webapp deployer
|
||||||
|
command: laconic-so deployment --dir webapp-deployer start
|
||||||
|
|
||||||
|
- name: Get the most recent pod for the deployment
|
||||||
|
shell: kubectl get pods --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}'
|
||||||
|
register: webapp_deployer_pod
|
||||||
|
|
||||||
|
- name: Set pod ID to a variable
|
||||||
|
set_fact:
|
||||||
|
pod_id: "{{ webapp_deployer_pod.stdout }}"
|
||||||
|
|
||||||
|
- name: Wait for the recent pod to be ready
|
||||||
|
command: kubectl wait --for=condition=Ready pod/{{ pod_id }} --timeout=300s
|
||||||
|
register: wait_result
|
||||||
|
|
||||||
|
- name: Copy gpg private key file to webapp deployer pod
|
||||||
|
shell: kubectl cp gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.key {{ pod_id }}:/app
|
||||||
|
|
||||||
|
- name: Copy gpg public key file to webapp deployer pod
|
||||||
|
shell: kubectl cp gpg-keys/webapp-deployer-api.{{ full_domain }}.pgp.pub {{ pod_id }}:/app
|
43
service-provider-setup/deploy-frontend.yml
Normal file
43
service-provider-setup/deploy-frontend.yml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
- name: Deploy webapp-deployer ui
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/webapp-vars.yml
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Clone webapp-deployment-status-ui repository
|
||||||
|
git:
|
||||||
|
repo: "https://git.vdb.to/cerc-io/webapp-deployment-status-ui.git"
|
||||||
|
dest: "{{ ansible_env.HOME }}/cerc/webapp-deployment-status-ui"
|
||||||
|
update: yes
|
||||||
|
|
||||||
|
- name: Build webapp-deployer-status-ui
|
||||||
|
command: laconic-so build-webapp --source-repo {{ ansible_env.HOME }}/cerc/webapp-deployment-status-ui
|
||||||
|
|
||||||
|
- name: Create a deployment for webapp-ui
|
||||||
|
command: |
|
||||||
|
laconic-so deploy-webapp create --kube-config {{ ansible_env.HOME }}/.kube/config-default.yaml
|
||||||
|
--image-registry container-registry.pwa.{{ full_domain }} --deployment-dir webapp-ui
|
||||||
|
--image cerc/webapp-deployment-status-ui:local --url https://webapp-deployer-ui.pwa.{{ full_domain }}
|
||||||
|
--env-file ~/cerc/webapp-deployment-status-ui/.env
|
||||||
|
|
||||||
|
- name: Push webapp-ui images to container registry
|
||||||
|
command: laconic-so deployment --dir webapp-ui push-images
|
||||||
|
|
||||||
|
- name: Update config file for webapp ui
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/webapp-ui-config.env.j2"
|
||||||
|
dest: "webapp-ui/config.env"
|
||||||
|
|
||||||
|
- name: Start the deployer ui
|
||||||
|
command: laconic-so deployment --dir webapp-ui start
|
||||||
|
|
||||||
|
- name: Create .out file
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/.out"
|
||||||
|
state: touch
|
91
service-provider-setup/run-laconic-console.yml
Normal file
91
service-provider-setup/run-laconic-console.yml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
- name: Setup and run laconic console
|
||||||
|
hosts: "{{target_host}}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/webapp-vars.yml
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
- vars/laconicd-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Clone the stack repo
|
||||||
|
command: laconic-so fetch-stack git.vdb.to/cerc-io/testnet-laconicd-stack --pull
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Clone required repositories for laconic-console
|
||||||
|
command: laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-console setup-repositories --pull
|
||||||
|
|
||||||
|
- name: Build container images
|
||||||
|
command: laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-console build-containers --force-rebuild
|
||||||
|
|
||||||
|
- name: Generate spec file for laconic console deployment
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/laconic-console-spec.yml.j2"
|
||||||
|
dest: "laconic-console-spec.yml"
|
||||||
|
|
||||||
|
- name: Check if the deployment directory exists
|
||||||
|
stat:
|
||||||
|
path: laconic-console-deployment
|
||||||
|
register: deployment_dir
|
||||||
|
|
||||||
|
- name: Create a deployment from the spec file
|
||||||
|
command: laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-console deploy create --spec-file laconic-console-spec.yml --deployment-dir laconic-console-deployment
|
||||||
|
when: not deployment_dir.stat.exists
|
||||||
|
|
||||||
|
- name: Place deployment in the same namespace as fixturenet-laconicd
|
||||||
|
copy:
|
||||||
|
src: "fixturenet-laconicd-deployment/deployment.yml"
|
||||||
|
dest: "laconic-console-deployment/deployment.yml"
|
||||||
|
remote_src: yes
|
||||||
|
|
||||||
|
- name: Fetch user key from laconicd
|
||||||
|
command: laconic-so deployment --dir fixturenet-laconicd-deployment exec laconicd "echo y | laconicd keys export alice --unarmored-hex --unsafe"
|
||||||
|
register: alice_pk
|
||||||
|
|
||||||
|
- name: Set Private key for console deployment
|
||||||
|
set_fact:
|
||||||
|
ALICE_PK: "{{ alice_pk.stdout }}"
|
||||||
|
|
||||||
|
- name: Check if DNS resolves for daemon
|
||||||
|
command: getent ahosts {{ org_id }}-daemon.{{ full_domain }}
|
||||||
|
register: dns_check
|
||||||
|
retries: 5
|
||||||
|
delay: 5
|
||||||
|
until: dns_check.rc == 0
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Fail if DNS does not resolve after retries
|
||||||
|
fail:
|
||||||
|
msg: "DNS resolution failed for example.com after 5 retries"
|
||||||
|
when: dns_check.rc != 0
|
||||||
|
|
||||||
|
- name: Start the laconic console deployment
|
||||||
|
command: laconic-so deployment --dir laconic-console-deployment start
|
||||||
|
|
||||||
|
- name: Create a bond using cli
|
||||||
|
shell: laconic-so deployment --dir laconic-console-deployment exec cli "laconic registry bond create --type alnt --quantity 1000000000000 --user-key {{ALICE_PK}}" | jq -r '.bondId'
|
||||||
|
register: bond_id
|
||||||
|
|
||||||
|
- name: Set Bond ID for console deployment
|
||||||
|
set_fact:
|
||||||
|
BOND_ID: "{{ bond_id.stdout }}"
|
||||||
|
|
||||||
|
- name: Stop the console deployment
|
||||||
|
command: laconic-so deployment --dir laconic-console-deployment stop
|
||||||
|
|
||||||
|
- name: Modify the console config with alice_pk and bond_id
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/console-config.env.j2"
|
||||||
|
dest: "laconic-console-deployment/config.env"
|
||||||
|
|
||||||
|
- name: Start the laconic console deployment with updated config
|
||||||
|
command: laconic-so deployment --dir laconic-console-deployment start
|
||||||
|
|
||||||
|
- name: Reserve an authority
|
||||||
|
command: laconic-so deployment --dir laconic-console-deployment exec cli "laconic registry authority reserve {{authority_name}}"
|
||||||
|
|
||||||
|
- name: Set authority using bond id
|
||||||
|
command: laconic-so deployment --dir laconic-console-deployment exec cli "laconic registry authority bond set {{authority_name}} {{BOND_ID}}"
|
41
service-provider-setup/run-laconicd.yml
Normal file
41
service-provider-setup/run-laconicd.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
- name: Setup and run fixturnet-laconicd-stack
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/laconicd-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Clone the fixturenet-laconicd-stack repo
|
||||||
|
command: laconic-so fetch-stack git.vdb.to/cerc-io/fixturenet-laconicd-stack --pull
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Setup repos for fixturenet-laconicd
|
||||||
|
command: laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd setup-repositories
|
||||||
|
|
||||||
|
- name: Build container images
|
||||||
|
command: laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd build-containers --force-rebuild
|
||||||
|
|
||||||
|
- name: Generate spec file for laconicd deployment
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/fixturenet-laconicd-spec.yml.j2"
|
||||||
|
dest: "fixturenet-laconicd-spec.yml"
|
||||||
|
|
||||||
|
- name: Check if the deployment directory exists
|
||||||
|
stat:
|
||||||
|
path: "fixturenet-laconicd-deployment"
|
||||||
|
register: deployment_dir
|
||||||
|
|
||||||
|
- name: Create the deployment from the spec file
|
||||||
|
command: laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd deploy create --spec-file fixturenet-laconicd-spec.yml --deployment-dir fixturenet-laconicd-deployment
|
||||||
|
when: not deployment_dir.stat.exists
|
||||||
|
|
||||||
|
- name: Create laconicd config
|
||||||
|
template:
|
||||||
|
src: "./templates/configs/laconicd-config.env.j2"
|
||||||
|
dest: "fixturenet-laconicd-deployment/config.env"
|
||||||
|
|
||||||
|
- name: Start the deployment
|
||||||
|
command: laconic-so deployment --dir fixturenet-laconicd-deployment start
|
20
service-provider-setup/service-provider-setup.yml
Normal file
20
service-provider-setup/service-provider-setup.yml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
- hosts: "{{ target_host }}"
|
||||||
|
tasks:
|
||||||
|
- name: Check if .out file exists
|
||||||
|
stat:
|
||||||
|
path: "{{ ansible_env.HOME }}/.out"
|
||||||
|
register: out_file
|
||||||
|
|
||||||
|
- name: Exit playbook if .out file exists
|
||||||
|
fail:
|
||||||
|
msg: ".out file exists, exiting playbook."
|
||||||
|
when: out_file.stat.exists
|
||||||
|
|
||||||
|
- import_playbook: setup-dns.yml
|
||||||
|
- import_playbook: setup-system.yml
|
||||||
|
- import_playbook: setup-k8s.yml
|
||||||
|
- import_playbook: setup-container-registry.yml
|
||||||
|
- import_playbook: run-laconicd.yml
|
||||||
|
- import_playbook: run-laconic-console.yml
|
||||||
|
- import_playbook: deploy-backend.yml
|
||||||
|
- import_playbook: deploy-frontend.yml
|
161
service-provider-setup/setup-container-registry.yml
Normal file
161
service-provider-setup/setup-container-registry.yml
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
- name: Setup container registry
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
- vars/container-vars.yml
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Generate spec file for the container-registry stack
|
||||||
|
template:
|
||||||
|
src: "./templates/specs/container-registry.spec.j2"
|
||||||
|
dest: "{{ansible_env.HOME}}/container-registry.spec"
|
||||||
|
|
||||||
|
- name: Create a deployment for the container-registry stack
|
||||||
|
command: laconic-so --stack container-registry deploy create --deployment-dir container-registry --spec-file container-registry.spec
|
||||||
|
|
||||||
|
- name: Base64 encode the container registry credentials
|
||||||
|
set_fact:
|
||||||
|
b64_encoded_cred: "{{ (container_registry_username + ':' + container_registry_password) | b64encode }}"
|
||||||
|
|
||||||
|
- name: Encrypt the container registry credentials to create an htpasswd file
|
||||||
|
command: >
|
||||||
|
htpasswd -bB -c container-registry/configmaps/config/htpasswd
|
||||||
|
{{ container_registry_username }} {{ container_registry_password }}
|
||||||
|
register: htpasswd_file
|
||||||
|
|
||||||
|
- name: Read the htpasswd file
|
||||||
|
slurp:
|
||||||
|
src: "container-registry/configmaps/config/htpasswd"
|
||||||
|
register: htpasswd_file_content
|
||||||
|
|
||||||
|
- name: Extract the hashed password (after the colon)
|
||||||
|
set_fact:
|
||||||
|
hashed_password: "{{ (htpasswd_file_content.content | b64decode).split(':')[1] | trim }}"
|
||||||
|
|
||||||
|
- name: Create container-registry/my_password.json file
|
||||||
|
template:
|
||||||
|
src: "./templates/my_password.json.j2"
|
||||||
|
dest: "container-registry/my_password.json"
|
||||||
|
|
||||||
|
- name: Configure the file container-registry/config.env
|
||||||
|
copy:
|
||||||
|
dest: "container-registry/config.env"
|
||||||
|
content: |
|
||||||
|
REGISTRY_AUTH=htpasswd
|
||||||
|
REGISTRY_AUTH_HTPASSWD_REALM="{{org_id}} Service Provider Image Registry"
|
||||||
|
REGISTRY_AUTH_HTPASSWD_PATH="/config/htpasswd"
|
||||||
|
REGISTRY_HTTP_SECRET='{{ hashed_password }}'
|
||||||
|
|
||||||
|
- name: Set KUBECONFIG environment variable
|
||||||
|
set_fact:
|
||||||
|
kubeconfig_path: "{{ ansible_env.HOME }}/.kube/config-default.yaml"
|
||||||
|
|
||||||
|
- name: Add the container registry credentials as a secret available to the cluster
|
||||||
|
command: >
|
||||||
|
kubectl create secret generic laconic-registry
|
||||||
|
--from-file=.dockerconfigjson=container-registry/my_password.json
|
||||||
|
--type=kubernetes.io/dockerconfigjson
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
|
||||||
|
# TODO: Investigate why container registry throws error if started immediately
|
||||||
|
- name: Wait for 90 seconds
|
||||||
|
pause:
|
||||||
|
seconds: 90
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Get Kubernetes nodes with wide output
|
||||||
|
command: kubectl get nodes -o wide
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
register: nodes_output
|
||||||
|
|
||||||
|
- name: Print output of 'kubectl get nodes -o wide'
|
||||||
|
debug:
|
||||||
|
var: nodes_output.stdout
|
||||||
|
|
||||||
|
- name: Get all secrets from all namespaces
|
||||||
|
command: kubectl get secrets --all-namespaces
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
register: secrets_output
|
||||||
|
|
||||||
|
- name: Print output of 'kubectl get secrets --all-namespaces'
|
||||||
|
debug:
|
||||||
|
var: secrets_output.stdout
|
||||||
|
|
||||||
|
- name: Get cluster issuers
|
||||||
|
command: kubectl get clusterissuer
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
register: clusterissuer_output
|
||||||
|
|
||||||
|
- name: Print output of 'kubectl get clusterissuer'
|
||||||
|
debug:
|
||||||
|
var: clusterissuer_output.stdout
|
||||||
|
|
||||||
|
- name: Get certificates
|
||||||
|
command: kubectl get certificates
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
register: certificates_output
|
||||||
|
|
||||||
|
- name: Print output of 'kubectl get certificates'
|
||||||
|
debug:
|
||||||
|
var: certificates_output.stdout
|
||||||
|
|
||||||
|
- name: Get DaemonSets in all namespaces
|
||||||
|
command: kubectl get ds --all-namespaces
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ kubeconfig_path }}"
|
||||||
|
register: daemonsets_output
|
||||||
|
|
||||||
|
- name: Print output of 'kubectl get ds --all-namespaces'
|
||||||
|
debug:
|
||||||
|
var: daemonsets_output.stdout
|
||||||
|
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Deploy the container registry
|
||||||
|
command: >
|
||||||
|
laconic-so deployment --dir container-registry start
|
||||||
|
|
||||||
|
- name: Get cluster_id from container-registry-deployment
|
||||||
|
slurp:
|
||||||
|
src: container-registry/deployment.yml
|
||||||
|
register: deployment_file
|
||||||
|
|
||||||
|
- name: Decode and extract cluster-id
|
||||||
|
set_fact:
|
||||||
|
extracted_cluster_id: "{{ deployment_file.content | b64decode | regex_search('cluster-id: (.+)', '\\1') }}"
|
||||||
|
|
||||||
|
- name: Set modified cluster-id
|
||||||
|
set_fact:
|
||||||
|
formatted_cluster_id: "{{ extracted_cluster_id | replace('[', '') | replace(']', '') | replace(\"'\", '') }}"
|
||||||
|
|
||||||
|
- name: Display the cluster ID
|
||||||
|
debug:
|
||||||
|
msg: "The cluster ID is: {{ formatted_cluster_id }}"
|
||||||
|
|
||||||
|
- name: Annotate ingress for proxy body size
|
||||||
|
command: >
|
||||||
|
kubectl annotate ingress {{ formatted_cluster_id }}-ingress nginx.ingress.kubernetes.io/proxy-body-size=0
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ ansible_env.HOME }}/.kube/config-default.yaml"
|
||||||
|
|
||||||
|
- name: Annotate ingress for proxy read timeout
|
||||||
|
command: >
|
||||||
|
kubectl annotate ingress {{ formatted_cluster_id }}-ingress nginx.ingress.kubernetes.io/proxy-read-timeout=600
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ ansible_env.HOME }}/.kube/config-default.yaml"
|
||||||
|
|
||||||
|
- name: Annotate ingress for proxy send timeout
|
||||||
|
command: >
|
||||||
|
kubectl annotate ingress {{ formatted_cluster_id }}-ingress nginx.ingress.kubernetes.io/proxy-send-timeout=600
|
||||||
|
environment:
|
||||||
|
KUBECONFIG: "{{ ansible_env.HOME }}/.kube/config-default.yaml"
|
122
service-provider-setup/setup-dns.yml
Normal file
122
service-provider-setup/setup-dns.yml
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
- name: Configure DNS records
|
||||||
|
hosts: localhost
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if domain exists
|
||||||
|
community.digitalocean.digital_ocean_domain_facts:
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
register: existing_domains
|
||||||
|
|
||||||
|
- name: Fail if domain already exists
|
||||||
|
fail:
|
||||||
|
msg: "Domain {{ full_domain }} already exists."
|
||||||
|
when: full_domain in existing_domains.data | map(attribute='name') | list
|
||||||
|
|
||||||
|
- name: Create a domain
|
||||||
|
community.digitalocean.digital_ocean_domain:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
name: "{{ full_domain }}"
|
||||||
|
ip: "{{ service_provider_ip }}"
|
||||||
|
|
||||||
|
- name: Create record for cluster control machine
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: A
|
||||||
|
name: "{{ subdomain_prefix }}-cluster-control"
|
||||||
|
data: "{{ service_provider_ip }}"
|
||||||
|
|
||||||
|
- name: Create record for daemon machine
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: A
|
||||||
|
name: "{{ org_id }}-daemon"
|
||||||
|
data: "{{ service_provider_ip }}"
|
||||||
|
|
||||||
|
- name: Create CNAME record for www
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
data: "{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
name: www
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create CNAME record for subdomain
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
data: "{{ subdomain_cluster_control }}.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
name: "{{ subdomain_prefix }}"
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create CNAME record for laconicd endpoint
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
data: "{{ org_id }}-daemon.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
name: "laconicd"
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create CNAME record for backend
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
data: "{{ org_id }}-daemon.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
name: "{{ org_id }}-backend"
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create CNAME record for console
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
data: "{{ org_id }}-daemon.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
name: "{{ org_id }}-console"
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create wildcard CNAME record for subdomain
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
name: "*.{{ subdomain_prefix }}"
|
||||||
|
data: "{{ subdomain_prefix }}-cluster-control.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create CNAME record for pwa
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
name: "pwa"
|
||||||
|
data: "{{ subdomain_prefix }}-cluster-control.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
ttl: 43200
|
||||||
|
|
||||||
|
- name: Create wildcard CNAME record for pwa
|
||||||
|
community.digitalocean.digital_ocean_domain_record:
|
||||||
|
state: present
|
||||||
|
oauth_token: "{{ do_api_token }}"
|
||||||
|
name: "*.pwa"
|
||||||
|
data: "{{ subdomain_prefix }}-cluster-control.{{ full_domain }}"
|
||||||
|
domain: "{{ full_domain }}"
|
||||||
|
type: CNAME
|
||||||
|
ttl: 43200
|
185
service-provider-setup/setup-k8s.yml
Normal file
185
service-provider-setup/setup-k8s.yml
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
- name: Install Stack Orchestrator if it isn't present
|
||||||
|
import_playbook: ../stack-orchestrator-setup/setup-laconic-so.yml
|
||||||
|
|
||||||
|
- name: Setup k8s
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/.local/bin"
|
||||||
|
VAULT_KEY: "{{ vault_passphrase }}"
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/gpg-vars.yml
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install Python and pip
|
||||||
|
apt:
|
||||||
|
name: "{{ item }}"
|
||||||
|
state: present
|
||||||
|
become: yes
|
||||||
|
loop:
|
||||||
|
- python3
|
||||||
|
- python3-pip
|
||||||
|
|
||||||
|
- name: Add user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: true
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Install Ansible on remote host
|
||||||
|
pip:
|
||||||
|
name: ansible
|
||||||
|
extra_args: --user
|
||||||
|
when: target_host != "localhost"
|
||||||
|
|
||||||
|
- name: Ensure ~/.local/bin is in PATH in .bashrc
|
||||||
|
lineinfile:
|
||||||
|
path: ~/.bashrc
|
||||||
|
line: 'export PATH="$HOME/.local/bin:$PATH"'
|
||||||
|
state: present
|
||||||
|
create: yes
|
||||||
|
|
||||||
|
- name: Ensure ~/.local/bin is in PATH in .zshrc
|
||||||
|
lineinfile:
|
||||||
|
path: ~/.zshrc
|
||||||
|
line: 'export PATH="$HOME/.local/bin:$PATH"'
|
||||||
|
state: present
|
||||||
|
create: yes
|
||||||
|
|
||||||
|
- name: Clone the service provider template repo
|
||||||
|
git:
|
||||||
|
repo: "https://git.vdb.to/cerc-io/service-provider-template.git"
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
|
||||||
|
- name: Update .vault/vault-keys file
|
||||||
|
lineinfile:
|
||||||
|
path: "service-provider-template/.vault/vault-keys"
|
||||||
|
regexp: '^.*$'
|
||||||
|
line: "{{ gpg_key_id }}"
|
||||||
|
create: yes
|
||||||
|
|
||||||
|
- name: Start GPG agent
|
||||||
|
command: gpg-agent --daemon
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
# Cache GPG passphrase by signing a dummy string to avoid passphrase prompts in later steps
|
||||||
|
- name: Sign a dummy string using gpg-key
|
||||||
|
shell: echo "This is a dummy string." | gpg --batch --yes --local-user "{{ gpg_key_id }}" --passphrase "{{ vault_passphrase }}" --pinentry-mode loopback --sign -
|
||||||
|
|
||||||
|
- name: Run vault-rekey.sh
|
||||||
|
shell: bash .vault/vault-rekey.sh
|
||||||
|
args:
|
||||||
|
chdir: "service-provider-template"
|
||||||
|
register: rekey_result
|
||||||
|
until: rekey_result.stderr == ""
|
||||||
|
retries: 5
|
||||||
|
delay: 5
|
||||||
|
|
||||||
|
- name: Ensure the target directory exists
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Change directory name in group_vars
|
||||||
|
command: mv lcn_cad {{ org_id }}_{{ location_id }}
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template/group_vars"
|
||||||
|
|
||||||
|
- name: Change control directory name in host_vars
|
||||||
|
command: mv lcn-cad-cluster-control {{ org_id }}-{{ location_id }}-cluster-control
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template/host_vars"
|
||||||
|
|
||||||
|
- name: Change daemon directory name in host_vars
|
||||||
|
command: mv lcn-daemon {{ org_id }}-daemon
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template/host_vars"
|
||||||
|
|
||||||
|
- name: Copy control-firewalld.yml to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/control-firewalld.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/host_vars/{{ org_id }}-{{ location_id }}-cluster-control/firewalld.yml"
|
||||||
|
|
||||||
|
- name: Copy daemon-firewalld.yml to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/daemon-firewalld.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/host_vars/{{ org_id }}-daemon/firewalld.yml"
|
||||||
|
|
||||||
|
- name: Copy nginx.yml to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/nginx.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/host_vars/{{ org_id }}-daemon/nginx.yml"
|
||||||
|
|
||||||
|
- name: Copy hosts file to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/hosts.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/hosts"
|
||||||
|
|
||||||
|
- name: Copy k8s.yml to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/k8s.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/group_vars/{{ org_id }}_{{ location_id }}/k8s.yml"
|
||||||
|
|
||||||
|
- name: Copy wildcard template to the remote VM
|
||||||
|
template:
|
||||||
|
src: ./templates/wildcard-pwa-example.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/files/manifests/wildcard-pwa-{{ full_domain | replace('.', '-') }}.yaml"
|
||||||
|
|
||||||
|
- name: Delete old wildcard-pwa file
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/service-provider-template/files/manifests/wildcard-pwa-laconic.yaml"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Install required ansible roles
|
||||||
|
shell: ansible-galaxy install -f -p roles -r roles/requirements.yml
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
|
||||||
|
- name: Install Kubernetes helper tools
|
||||||
|
shell: ./roles/k8s/files/scripts/get-kube-tools.sh
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Update group_vars/all/vault.yml with support email using template
|
||||||
|
template:
|
||||||
|
src: ./templates/vault.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/group_vars/all/vault.yml"
|
||||||
|
|
||||||
|
- name: Base64 encode DigitalOcean token
|
||||||
|
set_fact:
|
||||||
|
b64_encoded_token: "{{ do_api_token | b64encode }}"
|
||||||
|
|
||||||
|
- name: Update secret-digitalocean-dns.yaml with encoded token
|
||||||
|
template:
|
||||||
|
src: ./templates/secret-digitalocean-dns.yml.j2
|
||||||
|
dest: "{{ ansible_env.HOME }}/service-provider-template/files/manifests/secret-digitalocean-dns.yaml"
|
||||||
|
vars:
|
||||||
|
b64_encoded_token: "{{ b64_encoded_token }}"
|
||||||
|
|
||||||
|
- name: Remove k8s-vault.yml file
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/service-provider-template/group_vars/{{ org_id }}_{{ location_id }}/k8s-vault.yml"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Generate token for the cluster
|
||||||
|
command: ./roles/k8s/files/scripts/token-vault.sh ./group_vars/{{ org_id }}_{{ location_id }}/k8s-vault.yml
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
|
||||||
|
- name: Configure firewalld and nginx
|
||||||
|
command: ansible-playbook -i hosts site.yml --tags=firewalld,nginx
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template"
|
||||||
|
environment:
|
||||||
|
ANSIBLE_HOST_KEY_CHECKING: "False"
|
||||||
|
|
||||||
|
- name: Deploy Kubernetes
|
||||||
|
command: ansible-playbook -i hosts site.yml --tags=k8s --limit={{ org_id }}_{{ location_id }} --user {{ ansible_user }}
|
||||||
|
args:
|
||||||
|
chdir: "{{ ansible_env.HOME }}/service-provider-template"
|
137
service-provider-setup/setup-system.yml
Normal file
137
service-provider-setup/setup-system.yml
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
- name: Setup system for the service provider setup
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GNUPGHOME: /home/{{ ansible_user }}/.gnupg
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- vars/k8s-vars.yml
|
||||||
|
- vars/dns-vars.yml
|
||||||
|
- vars/gpg-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Install required packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- doas
|
||||||
|
- zsh
|
||||||
|
- tmux
|
||||||
|
- git
|
||||||
|
- jq
|
||||||
|
- acl
|
||||||
|
- curl
|
||||||
|
- wget
|
||||||
|
- netcat-traditional
|
||||||
|
- fping
|
||||||
|
- rsync
|
||||||
|
- htop
|
||||||
|
- iotop
|
||||||
|
- iftop
|
||||||
|
- tar
|
||||||
|
- less
|
||||||
|
- firewalld
|
||||||
|
- sshguard
|
||||||
|
- wireguard
|
||||||
|
- iproute2
|
||||||
|
- iperf3
|
||||||
|
- zfsutils-linux
|
||||||
|
- net-tools
|
||||||
|
- ca-certificates
|
||||||
|
- gnupg
|
||||||
|
- sshpass
|
||||||
|
- apache2-utils
|
||||||
|
state: latest
|
||||||
|
update_cache: true
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Set unique hostname
|
||||||
|
hostname:
|
||||||
|
name: "{{ inventory_hostname }}"
|
||||||
|
when: ansible_hostname != inventory_hostname
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Verify status of firewalld and enable sshguard
|
||||||
|
systemd:
|
||||||
|
name: "{{ item }}"
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
loop:
|
||||||
|
- firewalld
|
||||||
|
- sshguard
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Disable and remove snapd
|
||||||
|
block:
|
||||||
|
- name: Disable snapd services
|
||||||
|
systemd:
|
||||||
|
name: "{{ item }}"
|
||||||
|
enabled: no
|
||||||
|
state: stopped
|
||||||
|
loop:
|
||||||
|
- snapd.service
|
||||||
|
- snapd.socket
|
||||||
|
- snapd.seeded
|
||||||
|
- snapd.snap-repair.timer
|
||||||
|
ignore_errors: yes
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Purge snapd
|
||||||
|
apt:
|
||||||
|
name: snapd
|
||||||
|
state: absent
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Remove snap directories
|
||||||
|
file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: absent
|
||||||
|
loop:
|
||||||
|
- "{{ ansible_env.HOME }}/snap"
|
||||||
|
- /snap
|
||||||
|
- /var/snap
|
||||||
|
- /var/lib/snapd
|
||||||
|
become: yes
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Ensure GPG directory exists
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/.gnupg"
|
||||||
|
state: directory
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Create GPG key parameters file
|
||||||
|
copy:
|
||||||
|
dest: /tmp/gpg_key_params.txt
|
||||||
|
content: |
|
||||||
|
Key-Type: RSA
|
||||||
|
Key-Length: 4096
|
||||||
|
Subkey-Type: RSA
|
||||||
|
Name-Real: {{ gpg_user_name }}
|
||||||
|
Name-Email: {{ gpg_user_email }}
|
||||||
|
Expire-Date: 0
|
||||||
|
Passphrase: {{ gpg_passphrase }}
|
||||||
|
%no-protection
|
||||||
|
%commit
|
||||||
|
mode: '0600'
|
||||||
|
|
||||||
|
- name: Generate GPG key using the parameter file
|
||||||
|
command: gpg --batch --gen-key /tmp/gpg_key_params.txt
|
||||||
|
become_user: "{{ ansible_user }}"
|
||||||
|
register: gpg_keygen_output
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- name: Show GPG key generation output
|
||||||
|
debug:
|
||||||
|
var: gpg_keygen_output.stdout
|
||||||
|
|
||||||
|
- name: Fetch the Key ID of the most recently created GPG key
|
||||||
|
shell: gpg --list-secret-keys --keyid-format=long | grep 'sec' | tail -n 1 | awk -F'/' '{print $2}' | awk '{print $1}'
|
||||||
|
register: gpg_key_output
|
||||||
|
|
||||||
|
- name: Set the GPG key ID to a variable
|
||||||
|
set_fact:
|
||||||
|
sec_key_id: "{{ gpg_key_output.stdout }}"
|
||||||
|
|
||||||
|
- name: Show GPG Key ID
|
||||||
|
debug:
|
||||||
|
msg: "GPG Key ID: {{ sec_key_id }}"
|
@ -0,0 +1,6 @@
|
|||||||
|
CERC_LACONICD_USER_KEY={{ALICE_PK}}
|
||||||
|
CERC_LACONICD_BOND_ID={{BOND_ID}}
|
||||||
|
CERC_LACONICD_RPC_ENDPOINT=http://{{ org_id }}-daemon.{{ full_domain }}:26657
|
||||||
|
CERC_LACONICD_GQL_ENDPOINT=http://{{ org_id }}-daemon.{{ full_domain }}:9473/api
|
||||||
|
CERC_LACONICD_CHAIN_ID={{ chain_id }}
|
||||||
|
LACONIC_HOSTED_ENDPOINT=http://{{ org_id }}-daemon.{{ full_domain }}:9473
|
@ -0,0 +1 @@
|
|||||||
|
CHAINID={{ chain_id }}
|
@ -0,0 +1,30 @@
|
|||||||
|
DEPLOYMENT_DNS_SUFFIX="pwa.{{ full_domain }}"
|
||||||
|
|
||||||
|
# Name of reserved authority
|
||||||
|
DEPLOYMENT_RECORD_NAMESPACE="{{ authority_name }}"
|
||||||
|
|
||||||
|
# url of the deployed docker image registry
|
||||||
|
IMAGE_REGISTRY="container-registry.pwa.{{ full_domain }}"
|
||||||
|
|
||||||
|
# htpasswd credentials
|
||||||
|
IMAGE_REGISTRY_USER="{{ container_registry_username }}"
|
||||||
|
IMAGE_REGISTRY_CREDS="{{ container_registry_password }}"
|
||||||
|
|
||||||
|
# configs
|
||||||
|
CLEAN_DEPLOYMENTS=false
|
||||||
|
CLEAN_LOGS=false
|
||||||
|
CLEAN_CONTAINERS=false
|
||||||
|
SYSTEM_PRUNE=false
|
||||||
|
WEBAPP_IMAGE_PRUNE=true
|
||||||
|
CHECK_INTERVAL=5
|
||||||
|
FQDN_POLICY="allow"
|
||||||
|
|
||||||
|
# lrn of the webapp deployer
|
||||||
|
LRN="lrn://{{ authority_name }}/deployers/webapp-deployer-api.pwa.{{ full_domain }}"
|
||||||
|
export OPENPGP_PRIVATE_KEY_FILE="webapp-deployer-api.{{ full_domain }}.pgp.key"
|
||||||
|
export OPENPGP_PASSPHRASE="{{ deployer_gpg_passphrase }}"
|
||||||
|
export DEPLOYER_STATE="srv-test/deployments/autodeploy.state"
|
||||||
|
export UNDEPLOYER_STATE="srv-test/deployments/autoundeploy.state"
|
||||||
|
export UPLOAD_DIRECTORY="srv-test/uploads"
|
||||||
|
export HANDLE_AUCTION_REQUESTS={{ handle_auction_requests }}
|
||||||
|
export AUCTION_BID_AMOUNT={{ auction_bid_amount }}
|
@ -0,0 +1,3 @@
|
|||||||
|
CERC_WEBAPP_DEBUG=0.1.0
|
||||||
|
LACONIC_HOSTED_CONFIG_app_api_url=https://webapp-deployer-api.pwa.{{ full_domain }}
|
||||||
|
LACONIC_HOSTED_CONFIG_app_console_link=http://{{ org_id }}-daemon.{{ full_domain }}:9473/console?query=%0A%20%20fragment%20ValueParts%20on%20Value%20%7B%0A%20%20%20%20...%20on%20BooleanValue%20%7B%0A%20%20%20%20%20%20bool%3A%20value%0A%20%20%20%20%7D%0A%20%20%20%20...%20on%20IntValue%20%7B%0A%20%20%20%20%20%20int%3A%20value%0A%20%20%20%20%7D%0A%20%20%20%20...%20on%20FloatValue%20%7B%0A%20%20%20%20%20%20float%3A%20value%0A%20%20%20%20%7D%0A%20%20%20%20...%20on%20StringValue%20%7B%0A%20%20%20%20%20%20string%3A%20value%0A%20%20%20%20%7D%0A%20%20%20%20...%20on%20BytesValue%20%7B%0A%20%20%20%20%20%20bytes%3A%20value%0A%20%20%20%20%7D%0A%20%20%20%20...%20on%20LinkValue%20%7B%0A%20%20%20%20%20%20link%3A%20value%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20fragment%20AttrParts%20on%20Attribute%20%7B%0A%20%20%20%20key%0A%20%20%20%20value%20%7B%0A%20%20%20%20%20%20...ValueParts%0A%20%20%20%20%20%20...%20on%20ArrayValue%20%7B%0A%20%20%20%20%20%20%20%20value%20%7B%0A%20%20%20%20%20%20%20%20%20%20...ValueParts%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20%7B%0A%20%20%20%20getRecordsByIds(ids%3A%20%5B%22#RQID#%22%5D)%20%7B%0A%20%20%20%20%20%20id%0A%20%20%20%20%20%20names%0A%20%20%20%20%20%20bondId%0A%20%20%20%20%20%20createTime%0A%20%20%20%20%20%20expiryTime%0A%20%20%20%20%20%20owners%0A%20%20%20%20%20%20attributes%20%7B%0A%20%20%20%20%20%20%20%20...AttrParts%0A%20%20%20%20%20%20%20%20value%20%7B%0A%20%20%20%20%20%20%20%20%20%20...%20on%20MapValue%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20map%3A%20value%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20...AttrParts%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A
|
16
service-provider-setup/templates/control-firewalld.yml.j2
Normal file
16
service-provider-setup/templates/control-firewalld.yml.j2
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
firewalld_add:
|
||||||
|
- name: public
|
||||||
|
interfaces:
|
||||||
|
- enp9s0
|
||||||
|
services:
|
||||||
|
- http
|
||||||
|
- https
|
||||||
|
ports:
|
||||||
|
- 6443/tcp
|
||||||
|
|
||||||
|
- name: trusted
|
||||||
|
sources:
|
||||||
|
- 10.42.0.0/16
|
||||||
|
- 10.43.0.0/16
|
||||||
|
- {{ service_provider_ip }}
|
16
service-provider-setup/templates/daemon-firewalld.yml.j2
Normal file
16
service-provider-setup/templates/daemon-firewalld.yml.j2
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
firewalld_add:
|
||||||
|
- name: public
|
||||||
|
interfaces:
|
||||||
|
- ens3
|
||||||
|
services:
|
||||||
|
- http
|
||||||
|
- https
|
||||||
|
ports:
|
||||||
|
- 26657/tcp
|
||||||
|
- 26656/tcp
|
||||||
|
- 1317/tcp
|
||||||
|
|
||||||
|
- name: trusted
|
||||||
|
sources:
|
||||||
|
- {{ service_provider_ip }}
|
12
service-provider-setup/templates/hosts.j2
Normal file
12
service-provider-setup/templates/hosts.j2
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[all]
|
||||||
|
{{ org_id }}-daemon ansible_host={{ service_provider_ip }}
|
||||||
|
{{ org_id }}-{{ location_id }}-cluster-control ansible_host={{ service_provider_ip }}
|
||||||
|
|
||||||
|
[so]
|
||||||
|
{{ org_id }}-daemon
|
||||||
|
|
||||||
|
[{{ org_id }}_{{ location_id }}]
|
||||||
|
{{ org_id }}-{{ location_id }}-cluster-control k8s_node_type=bootstrap k8s_pod_limit=1024 k8s_external_ip={{ service_provider_ip }}
|
||||||
|
|
||||||
|
[k8s:children]
|
||||||
|
{{ org_id }}_{{ location_id }}
|
55
service-provider-setup/templates/k8s.yml.j2
Normal file
55
service-provider-setup/templates/k8s.yml.j2
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
# default context is used for stack orchestrator deployments, for testing a custom context name can be usefull
|
||||||
|
#k8s_cluster_name: {{ org_id }}-{{ location_id }}-cluster
|
||||||
|
k8s_cluster_name: default
|
||||||
|
k8s_cluster_url: {{ org_id }}-{{ location_id }}-cluster-control.{{ full_domain }}
|
||||||
|
k8s_taint_servers: false
|
||||||
|
|
||||||
|
k8s_acme_email: "{{ support_email }}"
|
||||||
|
|
||||||
|
# k3s bundles traefik as the default ingress controller, we will disable it and use nginx instead
|
||||||
|
k8s_disable:
|
||||||
|
- traefik
|
||||||
|
|
||||||
|
# secrets can be stored in a file or as a template, the template secrets gets dynamically base64 encoded while file based secrets must be encoded by hand
|
||||||
|
k8s_secrets:
|
||||||
|
- name: digitalocean-dns
|
||||||
|
type: file
|
||||||
|
source: secret-digitalocean-dns.yaml
|
||||||
|
|
||||||
|
k8s_manifests:
|
||||||
|
# ingress controller, replaces traefik which is explicitly disabled
|
||||||
|
- name: ingress-nginx
|
||||||
|
type: url
|
||||||
|
source: https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/cloud/deploy.yaml
|
||||||
|
|
||||||
|
# cert-manager, required for letsencrypt
|
||||||
|
- name: cert-manager
|
||||||
|
type: url
|
||||||
|
source: https://github.com/cert-manager/cert-manager/releases/download/v1.15.1/cert-manager.yaml
|
||||||
|
|
||||||
|
# issuer for basic http certs
|
||||||
|
- name: letsencrypt-prod
|
||||||
|
type: template
|
||||||
|
source: shared/clusterissuer-acme.yaml
|
||||||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
solvers:
|
||||||
|
- type: http
|
||||||
|
ingress: nginx
|
||||||
|
|
||||||
|
# issuer for wildcard dns certs
|
||||||
|
- name: letsencrypt-prod-wild
|
||||||
|
type: template
|
||||||
|
source: shared/clusterissuer-acme.yaml
|
||||||
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
solvers:
|
||||||
|
- type: dns
|
||||||
|
provider: digitalocean
|
||||||
|
tokenref: tokenSecretRef
|
||||||
|
secret_name: digitalocean-dns
|
||||||
|
secret_key: access-token
|
||||||
|
|
||||||
|
# initiate wildcard cert
|
||||||
|
- name: pwa.{{ full_domain }}
|
||||||
|
type: file
|
||||||
|
source: wildcard-pwa-{{ full_domain | replace('.', '-') }}.yaml
|
9
service-provider-setup/templates/laconic.yml.j2
Normal file
9
service-provider-setup/templates/laconic.yml.j2
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
registry:
|
||||||
|
rpcEndpoint: 'http://{{ org_id }}-daemon.{{ full_domain }}:26657'
|
||||||
|
gqlEndpoint: 'http://{{ org_id }}-daemon.{{ full_domain }}:9473/api'
|
||||||
|
userKey: "{{ ALICE_PK }}"
|
||||||
|
bondId: "{{ BOND_ID }}"
|
||||||
|
chainId: {{ chain_id }}
|
||||||
|
gas: 200000
|
||||||
|
fees: 200000alnt
|
9
service-provider-setup/templates/my_password.json.j2
Normal file
9
service-provider-setup/templates/my_password.json.j2
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"auths": {
|
||||||
|
"{{container_registry_domain}}": {
|
||||||
|
"username": "{{ container_registry_username }}",
|
||||||
|
"password": "{{ hashed_password }}",
|
||||||
|
"auth": "{{ b64_encoded_cred }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
service-provider-setup/templates/nginx.yml.j2
Normal file
21
service-provider-setup/templates/nginx.yml.j2
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
nginx_packages_intall: false
|
||||||
|
nginx_server_name_hash: 64
|
||||||
|
nginx_proxy_read_timeout: 1200
|
||||||
|
nginx_proxy_send_timeout: 1200
|
||||||
|
nginx_proxy_connection_timeout: 75
|
||||||
|
|
||||||
|
nginx_sites:
|
||||||
|
- name: {{ org_id }}-console
|
||||||
|
url: {{ org_id }}-console.{{ full_domain }}
|
||||||
|
upstream: http://localhost:8080
|
||||||
|
template: basic-proxy
|
||||||
|
ssl: true
|
||||||
|
|
||||||
|
- name: {{ org_id }}-daemon
|
||||||
|
url: {{ org_id }}-daemon.{{ full_domain }}
|
||||||
|
upstream: http://localhost:9473
|
||||||
|
configs:
|
||||||
|
- rewrite ^/deployer(/.*)? https://webapp-deployer.pwa.{{full_domain}} permanent
|
||||||
|
template: websocket-proxy
|
||||||
|
ssl: true
|
@ -0,0 +1,12 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cert-manager
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
data:
|
||||||
|
access-token: {{ b64_encoded_token }}
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: digitalocean-dns
|
||||||
|
namespace: cert-manager
|
@ -0,0 +1,16 @@
|
|||||||
|
stack: container-registry
|
||||||
|
deploy-to: k8s
|
||||||
|
kube-config: /home/{{ ansible_user }}/.kube/config-default.yaml
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
registry:
|
||||||
|
- '5000'
|
||||||
|
http-proxy:
|
||||||
|
- host-name: container-registry.pwa.{{full_domain}}
|
||||||
|
routes:
|
||||||
|
- path: '/'
|
||||||
|
proxy-to: registry:5000
|
||||||
|
volumes:
|
||||||
|
registry-data:
|
||||||
|
configmaps:
|
||||||
|
config: ./configmaps/config
|
@ -0,0 +1,15 @@
|
|||||||
|
stack:
|
||||||
|
/home/{{ansible_user}}/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd
|
||||||
|
deploy-to: compose
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
laconicd:
|
||||||
|
- '6060:6060'
|
||||||
|
- '26657:26657'
|
||||||
|
- '26656:26656'
|
||||||
|
- '9473:9473'
|
||||||
|
- '9090:9090'
|
||||||
|
- '1317:1317'
|
||||||
|
volumes:
|
||||||
|
laconicd-data: ./data/laconicd-data
|
||||||
|
genesis-config: ./data/genesis-config
|
@ -0,0 +1,9 @@
|
|||||||
|
stack:
|
||||||
|
/home/{{ansible_user}}/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-console
|
||||||
|
deploy-to: compose
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
console:
|
||||||
|
- '8080:80'
|
||||||
|
volumes:
|
||||||
|
laconic-registry-data: ./data/laconic-registry-data
|
@ -0,0 +1,35 @@
|
|||||||
|
stack: webapp-deployer-backend
|
||||||
|
deploy-to: k8s
|
||||||
|
kube-config: {{ansible_env.HOME}}/.kube/config-default.yaml
|
||||||
|
image-registry: container-registry.pwa.{{full_domain}}/laconic-registry
|
||||||
|
network:
|
||||||
|
ports:
|
||||||
|
server:
|
||||||
|
- '9555'
|
||||||
|
http-proxy:
|
||||||
|
- host-name: webapp-deployer-api.pwa.{{ full_domain }}
|
||||||
|
routes:
|
||||||
|
- path: '/'
|
||||||
|
proxy-to: server:9555
|
||||||
|
volumes:
|
||||||
|
srv:
|
||||||
|
configmaps:
|
||||||
|
config: ./data/config
|
||||||
|
annotations:
|
||||||
|
container.apparmor.security.beta.kubernetes.io/{name}: unconfined
|
||||||
|
labels:
|
||||||
|
container.kubeaudit.io/{name}.allow-disabled-apparmor: "podman"
|
||||||
|
security:
|
||||||
|
privileged: true
|
||||||
|
|
||||||
|
resources:
|
||||||
|
containers:
|
||||||
|
reservations:
|
||||||
|
cpus: {{ cpu_reservation }}
|
||||||
|
memory: {{ memory_reservation }}
|
||||||
|
limits:
|
||||||
|
cpus: {{ cpu_limit }}
|
||||||
|
memory: {{ memory_limit }}
|
||||||
|
volumes:
|
||||||
|
reservations:
|
||||||
|
storage: 200G
|
2
service-provider-setup/templates/vault.yml.j2
Normal file
2
service-provider-setup/templates/vault.yml.j2
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
support_email: {{ support_email }}
|
15
service-provider-setup/templates/wildcard-pwa-example.yml.j2
Normal file
15
service-provider-setup/templates/wildcard-pwa-example.yml.j2
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: cert-manager.io/v1
|
||||||
|
kind: Certificate
|
||||||
|
metadata:
|
||||||
|
name: pwa.{{ full_domain }}
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
secretName: pwa.{{ full_domain }}
|
||||||
|
issuerRef:
|
||||||
|
name: letsencrypt-prod-wild
|
||||||
|
kind: ClusterIssuer
|
||||||
|
group: cert-manager.io
|
||||||
|
commonName: "*.pwa.{{ full_domain }}"
|
||||||
|
dnsNames:
|
||||||
|
- "pwa.{{ full_domain }}"
|
||||||
|
- "*.pwa.{{ full_domain }}"
|
3
service-provider-setup/vars/container-vars.example.yml
Normal file
3
service-provider-setup/vars/container-vars.example.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
container_registry_username: ""
|
||||||
|
container_registry_password: ""
|
||||||
|
container_registry_domain: "container-registry.pwa.{{ full_domain }}"
|
5
service-provider-setup/vars/dns-vars.example.yml
Normal file
5
service-provider-setup/vars/dns-vars.example.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
full_domain: ""
|
||||||
|
subdomain_prefix: "{{ org_id }}-{{ location_id }}"
|
||||||
|
subdomain_cluster_control: "{{ subdomain_prefix }}-cluster-control"
|
||||||
|
service_provider_ip: ""
|
||||||
|
do_api_token: ""
|
3
service-provider-setup/vars/gpg-vars.example.yml
Normal file
3
service-provider-setup/vars/gpg-vars.example.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
gpg_user_name: ""
|
||||||
|
gpg_user_email: ""
|
||||||
|
gpg_passphrase: ""
|
6
service-provider-setup/vars/k8s-vars.example.yml
Normal file
6
service-provider-setup/vars/k8s-vars.example.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
gpg_key_id: "{{ sec_key_id }}"
|
||||||
|
vault_passphrase: "{{ gpg_passphrase }}"
|
||||||
|
org_id: ""
|
||||||
|
location_id: ""
|
||||||
|
support_email: ""
|
||||||
|
ansible_ssh_extra_args: '-o StrictHostKeyChecking=no'
|
1
service-provider-setup/vars/laconicd-vars.example.yml
Normal file
1
service-provider-setup/vars/laconicd-vars.example.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
chain_id: "laconic_9000-1"
|
10
service-provider-setup/vars/webapp-vars.example.yml
Normal file
10
service-provider-setup/vars/webapp-vars.example.yml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
ALICE_PK: "{{ ALICE_PK }}"
|
||||||
|
BOND_ID: "{{ BOND_ID }}"
|
||||||
|
authority_name: ""
|
||||||
|
cpu_reservation: "1"
|
||||||
|
memory_reservation: "2G"
|
||||||
|
cpu_limit: "6"
|
||||||
|
memory_limit: "8G"
|
||||||
|
deployer_gpg_passphrase: ""
|
||||||
|
handle_auction_requests: "true"
|
||||||
|
auction_bid_amount: "500000"
|
1
stack-orchestrator-setup/.gitignore
vendored
Normal file
1
stack-orchestrator-setup/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
hosts.ini
|
94
stack-orchestrator-setup/README.md
Normal file
94
stack-orchestrator-setup/README.md
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# stack-orchestrator-setup
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: To get started, follow the [installation](../README.md#installation) guide to setup ansible on your machine.
|
||||||
|
|
||||||
|
- Setup user with passwordless sudo: Follow steps from [Setup a user](../user-setup/README.md#setup-a-user) to setup a new user with passwordless sudo
|
||||||
|
|
||||||
|
## Setup Stack Orchestrator
|
||||||
|
|
||||||
|
This playbook will install Docker and Stack Orchestrator (laconic-so) on the machine if they aren't already present.
|
||||||
|
|
||||||
|
Run the following commands in the [`stack-orchestrator-setup`](./) directory.
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file to run the playbook on a remote machine:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[deployment_host]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<host_name>` with the alias of your choice
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Replace `<ssh_user>` with the username of the user that you set up on target machine (e.g. dev, ubuntu)
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Execute the `setup-laconic-so.yml` Ansible playbook for setting up stack orchestrator and docker on the target machine:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook setup-laconic-so.yml -i hosts.ini --extra-vars='{ "target_host": "deployment_host"}' --user $USER
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verify Installation
|
||||||
|
|
||||||
|
Run the following commands on your target machine:
|
||||||
|
|
||||||
|
- After the installation is complete, verify if `$HOME/bin` is already included in the `PATH` by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo $PATH | grep -q "$HOME/bin" && echo "$HOME/bin is already in PATH" || echo "$HOME/bin is not in PATH"
|
||||||
|
```
|
||||||
|
If the command outputs `"$HOME/bin is not in PATH"`, you'll need to add it to your `PATH`.
|
||||||
|
|
||||||
|
- To add `$HOME/bin` to your `PATH`, run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export PATH="$HOME/bin:$PATH"
|
||||||
|
```
|
||||||
|
|
||||||
|
- To make this change permanent, add the following line to your shell configuration file (`~/.bashrc` or `~/.zshrc`, depending on your shell):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For bash users
|
||||||
|
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
|
||||||
|
source ~/.bashrc
|
||||||
|
|
||||||
|
# For zsh users
|
||||||
|
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc
|
||||||
|
source ~/.zshrc
|
||||||
|
```
|
||||||
|
|
||||||
|
- Once the PATH is set, verify the installation by running the following commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check version of docker
|
||||||
|
docker --version
|
||||||
|
|
||||||
|
# Check version of docker compose
|
||||||
|
docker compose version
|
||||||
|
|
||||||
|
# Check version of Stack Orchestrator
|
||||||
|
laconic-so version
|
||||||
|
```
|
91
stack-orchestrator-setup/setup-docker.yml
Normal file
91
stack-orchestrator-setup/setup-docker.yml
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
- name: Set up Docker
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
vars:
|
||||||
|
target_host: "localhost"
|
||||||
|
docker_gpg_key_url: "https://download.docker.com/linux/ubuntu/gpg"
|
||||||
|
docker_gpg_key_path: "/etc/apt/keyrings/docker.asc"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if Docker is installed
|
||||||
|
command: which docker
|
||||||
|
register: is_docker_present
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Exit if docker is present
|
||||||
|
debug:
|
||||||
|
msg: "Docker already on host, ending play"
|
||||||
|
- meta: end_play
|
||||||
|
when: is_docker_present.rc == 0
|
||||||
|
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Install prerequisites
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- ca-certificates
|
||||||
|
- curl
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Ensure keyrings directory exists
|
||||||
|
file:
|
||||||
|
path: "/etc/apt/keyrings"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Download Docker GPG key
|
||||||
|
get_url:
|
||||||
|
url: "{{ docker_gpg_key_url }}"
|
||||||
|
dest: "{{ docker_gpg_key_path }}"
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Get system architecture
|
||||||
|
shell: dpkg --print-architecture
|
||||||
|
register: system_arch
|
||||||
|
|
||||||
|
- name: Add Docker repository
|
||||||
|
apt_repository:
|
||||||
|
repo: "deb [arch={{ system_arch.stdout }} signed-by={{ docker_gpg_key_path }}] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable"
|
||||||
|
state: present
|
||||||
|
filename: docker
|
||||||
|
|
||||||
|
- name: Update apt cache
|
||||||
|
apt:
|
||||||
|
update_cache: yes
|
||||||
|
|
||||||
|
- name: Install Docker packages
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- docker-ce
|
||||||
|
- docker-ce-cli
|
||||||
|
- containerd.io
|
||||||
|
- docker-buildx-plugin
|
||||||
|
- docker-compose-plugin
|
||||||
|
state: latest
|
||||||
|
notify: Restart Docker
|
||||||
|
|
||||||
|
- name: Add user to docker group
|
||||||
|
user:
|
||||||
|
name: "{{ ansible_user }}"
|
||||||
|
groups: docker
|
||||||
|
append: true
|
||||||
|
|
||||||
|
- name: Verify Docker installation by running the hello world image
|
||||||
|
command: docker run hello-world
|
||||||
|
register: hello_world_output
|
||||||
|
ignore_errors: true
|
||||||
|
become: no
|
||||||
|
|
||||||
|
- name: Display hello-world output
|
||||||
|
debug:
|
||||||
|
var: hello_world_output.stdout_lines
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- name: Restart Docker
|
||||||
|
service:
|
||||||
|
name: docker
|
||||||
|
state: restarted
|
57
stack-orchestrator-setup/setup-laconic-so.yml
Normal file
57
stack-orchestrator-setup/setup-laconic-so.yml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
- name: Install Docker if it isn't present
|
||||||
|
import_playbook: setup-docker.yml
|
||||||
|
|
||||||
|
- name: Set up Stack Orchestrator
|
||||||
|
hosts: "{{ target_host }}"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
target_host: "localhost"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
PATH: "{{ ansible_env.PATH }}:/home/{{ansible_user}}/bin"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Check if Stack Orchestrator is installed
|
||||||
|
shell: which laconic-so
|
||||||
|
register: is_so_present
|
||||||
|
ignore_errors: yes
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: Exit if Stack Orchestrator is present
|
||||||
|
debug:
|
||||||
|
msg: "Stack Orchestrator already on host, ending play"
|
||||||
|
- meta: end_play
|
||||||
|
when: is_so_present.rc == 0
|
||||||
|
|
||||||
|
- name: Install jq
|
||||||
|
apt:
|
||||||
|
name: jq
|
||||||
|
state: present
|
||||||
|
update_cache: yes
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
- name: Ensure that directory ~/bin exists and is writable
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/bin"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Download the laconic-so binary
|
||||||
|
get_url:
|
||||||
|
url: https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so
|
||||||
|
dest: "{{ ansible_env.HOME }}/bin/laconic-so"
|
||||||
|
mode: '0755'
|
||||||
|
force: yes
|
||||||
|
|
||||||
|
- name: Ensure ~/.laconic-so directory exists
|
||||||
|
file:
|
||||||
|
path: "{{ ansible_env.HOME }}/.laconic-so"
|
||||||
|
state: directory
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Save the distribution url to ~/.laconic-so directory
|
||||||
|
copy:
|
||||||
|
dest: "{{ ansible_env.HOME }}/.laconic-so/config.yml"
|
||||||
|
content: |
|
||||||
|
distribution-url: https://git.vdb.to/cerc-io/stack-orchestrator/releases/download/latest/laconic-so
|
||||||
|
mode: '0644'
|
1
user-setup/.gitignore
vendored
Normal file
1
user-setup/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
user-vars.yml
|
75
user-setup/README.md
Normal file
75
user-setup/README.md
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# user-setup
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Setup Ansible: follow the [installation](../README.md#installation) guide to setup ansible on your machine.
|
||||||
|
|
||||||
|
- Setup a remote machine with passwordless SSH login for the root user
|
||||||
|
|
||||||
|
- Install `passlib` used for handling encrypted passwords when setting up a user
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install passlib
|
||||||
|
```
|
||||||
|
|
||||||
|
## Setup a user
|
||||||
|
|
||||||
|
Execute the following commands in the `user-setup` directory
|
||||||
|
|
||||||
|
- Create a new `hosts.ini` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp ../hosts.example.ini hosts.ini
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the [`hosts.ini`](./hosts.ini) file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
[deployment_host]
|
||||||
|
<host_name> ansible_host=<target_ip> ansible_user=<ssh_user> ansible_ssh_common_args='-o ForwardAgent=yes'
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `<host_name>` with the desired `hostname` of the remote machine
|
||||||
|
- Replace `<target_ip>` with the IP address or hostname of the target machine
|
||||||
|
- Replace `<ssh_user>` with `root`
|
||||||
|
|
||||||
|
- Verify that you are able to connect to the host using the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ansible all -m ping -i hosts.ini
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
|
||||||
|
# <host_name> | SUCCESS => {
|
||||||
|
# "ansible_facts": {
|
||||||
|
# "discovered_interpreter_python": "/usr/bin/python3.10"
|
||||||
|
# },
|
||||||
|
# "changed": false,
|
||||||
|
# "ping": "pong"
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
- Setup `user-vars.yml` using the example file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp user-vars.example.yml user-vars.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
- Edit the `user-vars.yml` file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# name of the user you want to setup on the target host
|
||||||
|
username: ""
|
||||||
|
|
||||||
|
# password of the user you want to setup on the target host
|
||||||
|
password: ""
|
||||||
|
|
||||||
|
# path to the ssh key on your machine, eg: "/home/user/.ssh/id_rsa.pub"
|
||||||
|
path_to_ssh_key: ""
|
||||||
|
```
|
||||||
|
|
||||||
|
- Execute the `setup-user.yml` Ansible playbook to create a user with passwordless sudo permissions:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LANG=en_US.utf8 ansible-playbook setup-user.yml -i hosts.ini
|
||||||
|
```
|
46
user-setup/setup-user.yml
Normal file
46
user-setup/setup-user.yml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
- name: Configure system
|
||||||
|
hosts: deployment_host
|
||||||
|
become: yes
|
||||||
|
|
||||||
|
vars_files:
|
||||||
|
- user-vars.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create a user
|
||||||
|
user:
|
||||||
|
name: "{{ username }}"
|
||||||
|
password: "{{ '{{ password }}' | password_hash('sha512') }}"
|
||||||
|
shell: /bin/bash
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add user to sudoers group
|
||||||
|
user:
|
||||||
|
name: "{{ username }}"
|
||||||
|
groups: sudo
|
||||||
|
append: yes
|
||||||
|
|
||||||
|
- name: Ensure .ssh directory exists for user
|
||||||
|
file:
|
||||||
|
path: /home/{{ username }}/.ssh
|
||||||
|
state: directory
|
||||||
|
owner: "{{ username }}"
|
||||||
|
group: "{{ username }}"
|
||||||
|
mode: '0700'
|
||||||
|
|
||||||
|
- name: Append SSH public key to authorized_keys
|
||||||
|
lineinfile:
|
||||||
|
path: /home/{{ username }}/.ssh/authorized_keys
|
||||||
|
line: "{{ lookup('file', path_to_ssh_key) }}"
|
||||||
|
create: yes
|
||||||
|
owner: "{{ username }}"
|
||||||
|
group: "{{ username }}"
|
||||||
|
mode: '0600'
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add user to sudoers for passwordless sudo
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/sudoers
|
||||||
|
state: present
|
||||||
|
regexp: '^{{ username }} ALL=\(ALL\) NOPASSWD:ALL'
|
||||||
|
line: '{{ username }} ALL=(ALL) NOPASSWD:ALL'
|
||||||
|
validate: 'visudo -cf %s'
|
3
user-setup/user-vars.example.yml
Normal file
3
user-setup/user-vars.example.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
username: ""
|
||||||
|
password: ""
|
||||||
|
path_to_ssh_key: ""
|
Loading…
Reference in New Issue
Block a user