mirror of
https://github.com/replicatedhq/ttl.sh.git
synced 2026-07-10 14:49:38 +00:00
rework everything to be Ansible and get TLS working
This commit is contained in:
11
DEPLOYING.md
11
DEPLOYING.md
@@ -29,10 +29,7 @@
|
||||
1. Doppler is installed and authenticated for use with the `ttl-sh` project
|
||||
a. Have a valid `DOPPLER_TOKEN` from `ttl-sh` set
|
||||
b. `echo $DOPPLER_TOKEN | doppler configure set token --scope /`
|
||||
2. `./install.sh`
|
||||
3. Successful run states:
|
||||
a. `Container ttlsh-redis Started`
|
||||
b. `Container ttlsh-hooks Started`
|
||||
b. `Container ttlsh-reaper Started`
|
||||
c. `Container ttlsh-registry Started`
|
||||
d. `Container ttlsh-nginx Started`
|
||||
2. `cd ansible`
|
||||
3. `./ansible.sh`
|
||||
4. Successful run indicates approximately the following:
|
||||
a. `ok=42 changed=6 unreachable=0 failed=0 skipped=3`
|
||||
|
||||
12
ansible/ansible.cfg
Normal file
12
ansible/ansible.cfg
Normal file
@@ -0,0 +1,12 @@
|
||||
[defaults]
|
||||
inventory = ./inventory/hosts
|
||||
interpreter_python = auto_silent
|
||||
retry_files_enabled = False
|
||||
stdout_callback = default
|
||||
bin_ansible_callbacks = True
|
||||
|
||||
[callback_default]
|
||||
result_format = yaml
|
||||
|
||||
[ssh_connection]
|
||||
pipelining = True
|
||||
66
ansible/ansible.sh
Executable file
66
ansible/ansible.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Minimal wrapper to run Ansible with Cloudflare vars resolved via Doppler.
|
||||
# Usage:
|
||||
# bash ansible.sh
|
||||
|
||||
HERE="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
require_bin() {
|
||||
command -v "$1" >/dev/null 2>&1 || {
|
||||
echo "error: required command not found: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
require_env() {
|
||||
local name=$1
|
||||
if [[ -z "${!name:-}" ]]; then
|
||||
echo "error: required env var not set: $name" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_secret() {
|
||||
local key=$1
|
||||
# Uses DOPPLER_TOKEN from environment; Doppler CLI will read it.
|
||||
# --plain prints only the value with a trailing newline, strip it.
|
||||
local val
|
||||
if ! val=$(doppler secrets get "$key" --plain 2>/dev/null); then
|
||||
echo "error: failed to fetch secret '$key' from Doppler" >&2
|
||||
exit 1
|
||||
fi
|
||||
printf %s "$val"
|
||||
}
|
||||
|
||||
main() {
|
||||
require_bin ansible-playbook
|
||||
require_bin doppler
|
||||
require_env DOPPLER_TOKEN
|
||||
|
||||
# Always run from the ansible dir so relative paths match
|
||||
cd "$HERE"
|
||||
|
||||
ansible-playbook \
|
||||
-e "cloudflare_api_token=$(get_secret CF_API_TOKEN)" \
|
||||
-e "cloudflare_zone_id=$(get_secret CF_ZONE_ID)" \
|
||||
-e "cloudflare_email=$(get_secret LE_EMAIL)" \
|
||||
-e "le_email=$(get_secret LE_EMAIL)" \
|
||||
-e "gcloud_sa_email=$(get_secret GOOGLE_APPLICATION_CREDENTIALS_EMAIL)" \
|
||||
-e "gcloud_sa_key_json=$(get_secret GCS_KEY_ENCODED)" \
|
||||
-e "gcloud_registry_host=$(get_secret GOOGLE_CLOUD_ARTIFACT_REGISTRY_URI)" \
|
||||
-e "gcs_key_encoded=$(get_secret GCS_KEY_ENCODED)" \
|
||||
-e "hook_token=$(get_secret HOOK_TOKEN)" \
|
||||
-e "hook_uri=$(get_secret HOOK_URI)" \
|
||||
-e "redis_password=$(get_secret REDIS_PASSWORD)" \
|
||||
-e "rediscloud_url=$(get_secret REDISCLOUD_URL)" \
|
||||
-e "replreg_host=$(get_secret REPLREG_HOST)" \
|
||||
-e "replreg_secret=$(get_secret REPLREG_SECRET)" \
|
||||
-e "registry_url=$(get_secret REGISTRY_URL)" \
|
||||
playbooks/site.yml
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
45
ansible/inventory/group_vars/all.yml
Normal file
45
ansible/inventory/group_vars/all.yml
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
# Domain to provision
|
||||
domain_name: ttl.sh
|
||||
|
||||
# Compute zone name from domain (ttl.sh)
|
||||
zone_name: "ttl.sh"
|
||||
|
||||
# Cloudflare details
|
||||
cloudflare_zone_id: "_in_doppler"
|
||||
cloudflare_api_token: "_in_doppler"
|
||||
cloudflare_email: "_in_doppler"
|
||||
cloudflare_proxied: false
|
||||
|
||||
# A record target
|
||||
target_ip: 178.156.198.215
|
||||
|
||||
# Let's Encrypt contact email (using provided email)
|
||||
le_email: "_in_doppler"
|
||||
|
||||
# Repo path (relative to repo root) for static assets; easy to change later
|
||||
static_site_repo_path: static
|
||||
|
||||
# Google Cloud (gcloud) configuration
|
||||
# Provide the service account email and base64-encoded JSON key to configure auth.
|
||||
gcloud_sa_email: "_in_doppler"
|
||||
gcloud_sa_key_json: "_in_doppler"
|
||||
# Artifact Registry hostname to configure Docker for
|
||||
gcloud_registry_host: "_in_doppler"
|
||||
|
||||
# Docker install settings
|
||||
docker_users:
|
||||
- root
|
||||
|
||||
# Application deployment
|
||||
app_root: /opt/ttlsh
|
||||
|
||||
# Docker Compose .env
|
||||
gcs_key_encoded: "_in_doppler"
|
||||
hook_token: "_in_doppler"
|
||||
hook_uri: "_in_doppler"
|
||||
redis_password: "_in_doppler"
|
||||
rediscloud_url: "_in_doppler"
|
||||
replreg_host: "_in_doppler"
|
||||
replreg_secret: "_in_doppler"
|
||||
registry_url: "_in_doppler"
|
||||
2
ansible/inventory/hosts
Normal file
2
ansible/inventory/hosts
Normal file
@@ -0,0 +1,2 @@
|
||||
[ttlsh]
|
||||
178.156.198.215 ansible_user=root
|
||||
285
ansible/playbooks/site.yml
Normal file
285
ansible/playbooks/site.yml
Normal file
@@ -0,0 +1,285 @@
|
||||
---
|
||||
# Single play: run everything against the remote host
|
||||
- name: Install and configure Nginx + Certbot (Cloudflare DNS-01)
|
||||
hosts: ttlsh
|
||||
become: true
|
||||
vars:
|
||||
site_dir: "/var/www/{{ domain_name }}/html"
|
||||
cloudflare_credentials_path: /etc/letsencrypt/cloudflare.ini
|
||||
# derive DNS record prefix, e.g. 'dev' for dev.ttl.sh
|
||||
dns_record: "{{ '@' if domain_name == zone_name else domain_name[:-(zone_name|length + 1)] }}"
|
||||
# repo-relative source for static assets
|
||||
static_src_path: "{{ playbook_dir }}/../../{{ static_site_repo_path }}/"
|
||||
pre_tasks: []
|
||||
tasks:
|
||||
- name: Ensure Cloudflare API token present
|
||||
ansible.builtin.assert:
|
||||
that: cloudflare_api_token is defined and (cloudflare_api_token | length) > 0
|
||||
fail_msg: "cloudflare_api_token is missing."
|
||||
|
||||
- name: Ensure A record for {{ domain_name }} -> {{ target_ip }} (Cloudflare)
|
||||
community.general.cloudflare_dns:
|
||||
zone: "{{ zone_name }}"
|
||||
record: "{{ dns_record }}"
|
||||
type: A
|
||||
value: "{{ target_ip }}"
|
||||
proxied: "{{ cloudflare_proxied }}"
|
||||
api_token: "{{ cloudflare_api_token }}"
|
||||
|
||||
- name: Install packages
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- nginx
|
||||
- certbot
|
||||
- python3-certbot-dns-cloudflare
|
||||
update_cache: true
|
||||
state: present
|
||||
|
||||
- name: Ensure nginx is enabled and started
|
||||
ansible.builtin.service:
|
||||
name: nginx
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Write Cloudflare credentials for Certbot
|
||||
ansible.builtin.template:
|
||||
src: ../templates/cloudflare.ini.j2
|
||||
dest: "{{ cloudflare_credentials_path }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
|
||||
- name: Check if certificate already exists
|
||||
ansible.builtin.stat:
|
||||
path: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||
register: cert_stat
|
||||
|
||||
- name: Obtain certificate using DNS-01 (Cloudflare)
|
||||
ansible.builtin.command: >-
|
||||
certbot certonly
|
||||
--agree-tos
|
||||
--email {{ le_email }}
|
||||
--key-type ecdsa
|
||||
--elliptic-curve secp384r1
|
||||
--dns-cloudflare
|
||||
--dns-cloudflare-credentials {{ cloudflare_credentials_path }}
|
||||
--dns-cloudflare-propagation-seconds 60
|
||||
-d {{ domain_name }}
|
||||
--non-interactive
|
||||
args:
|
||||
creates: "/etc/letsencrypt/live/{{ domain_name }}/fullchain.pem"
|
||||
when: not cert_stat.stat.exists
|
||||
|
||||
- name: Create web root
|
||||
ansible.builtin.file:
|
||||
path: "{{ site_dir }}"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0755"
|
||||
recurse: true
|
||||
|
||||
- name: Deploy static assets from repo
|
||||
ansible.builtin.copy:
|
||||
src: "{{ static_src_path }}"
|
||||
dest: "{{ site_dir }}/"
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0644"
|
||||
directory_mode: "0755"
|
||||
|
||||
- name: Remove legacy test index.html if present
|
||||
ansible.builtin.file:
|
||||
path: "{{ site_dir }}/index.html"
|
||||
state: absent
|
||||
|
||||
- name: Drop Nginx site config (TLS enabled)
|
||||
ansible.builtin.template:
|
||||
src: ../templates/nginx_site.conf.j2
|
||||
dest: "/etc/nginx/sites-available/{{ domain_name }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Disable default site if present (available)
|
||||
ansible.builtin.file:
|
||||
path: /etc/nginx/sites-available/default
|
||||
state: absent
|
||||
|
||||
- name: Disable default site if present (enabled)
|
||||
ansible.builtin.file:
|
||||
path: /etc/nginx/sites-enabled/default
|
||||
state: absent
|
||||
|
||||
- name: Enable {{ domain_name }} site
|
||||
ansible.builtin.file:
|
||||
src: "/etc/nginx/sites-available/{{ domain_name }}"
|
||||
dest: "/etc/nginx/sites-enabled/{{ domain_name }}"
|
||||
state: link
|
||||
force: true
|
||||
|
||||
- name: Test nginx configuration
|
||||
ansible.builtin.command: nginx -t
|
||||
register: nginx_test
|
||||
changed_when: false
|
||||
|
||||
- name: Reload nginx
|
||||
ansible.builtin.service:
|
||||
name: nginx
|
||||
state: reloaded
|
||||
|
||||
- name: Ensure nginx reloads on renewal
|
||||
ansible.builtin.copy:
|
||||
dest: /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
|
||||
content: |
|
||||
#!/bin/sh
|
||||
/bin/systemctl reload nginx
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
|
||||
- name: Add cron to renew twice daily
|
||||
ansible.builtin.cron:
|
||||
name: "Certbot renew"
|
||||
user: root
|
||||
minute: "0"
|
||||
hour: "*/12"
|
||||
job: "/usr/bin/certbot renew -q"
|
||||
|
||||
# --- Google Cloud CLI install and configuration ---
|
||||
- name: Install Google Cloud CLI (role)
|
||||
ansible.builtin.include_role:
|
||||
name: google.cloud.gcloud
|
||||
|
||||
- name: Ensure gcloud key directory exists
|
||||
ansible.builtin.file:
|
||||
path: /root/.gcloud
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0700"
|
||||
when: (gcloud_sa_email | length) > 0 and (gcloud_sa_key_json | length) > 0
|
||||
|
||||
- name: Write GCP service account key (decoded from base64)
|
||||
ansible.builtin.copy:
|
||||
dest: /root/.gcloud/sa.json
|
||||
content: "{{ gcloud_sa_key_json | b64decode }}"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0600"
|
||||
when: (gcloud_sa_email | length) > 0 and (gcloud_sa_key_json | length) > 0
|
||||
|
||||
- name: Check existing gcloud authenticated accounts
|
||||
ansible.builtin.command: gcloud auth list --format=value(account)
|
||||
register: gcloud_auth_list
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
environment:
|
||||
CLOUDSDK_CORE_DISABLE_PROMPTS: "1"
|
||||
when: (gcloud_sa_email | length) > 0 and (gcloud_sa_key_json | length) > 0
|
||||
|
||||
- name: Activate service account for gcloud
|
||||
ansible.builtin.command: >-
|
||||
gcloud auth activate-service-account {{ gcloud_sa_email }}
|
||||
--key-file=/root/.gcloud/sa.json --quiet
|
||||
environment:
|
||||
CLOUDSDK_CORE_DISABLE_PROMPTS: "1"
|
||||
when: (gcloud_sa_email | length) > 0 and (gcloud_sa_key_json | length) > 0 and (gcloud_sa_email not in (gcloud_auth_list.stdout_lines | default([])))
|
||||
|
||||
- name: Configure Docker auth for Artifact Registry
|
||||
ansible.builtin.command: >-
|
||||
gcloud auth configure-docker {{ gcloud_registry_host }} --quiet
|
||||
environment:
|
||||
CLOUDSDK_CORE_DISABLE_PROMPTS: "1"
|
||||
when: (gcloud_sa_email | length) > 0 and (gcloud_sa_key_json | length) > 0
|
||||
|
||||
# --- Docker Engine + Compose install ---
|
||||
- name: Install Docker prereqs
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- ca-certificates
|
||||
- curl
|
||||
- gnupg
|
||||
- lsb-release
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Ensure keyrings directory exists
|
||||
ansible.builtin.file:
|
||||
path: /etc/apt/keyrings
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Add Docker GPG key
|
||||
ansible.builtin.get_url:
|
||||
url: https://download.docker.com/linux/ubuntu/gpg
|
||||
dest: /etc/apt/keyrings/docker.asc
|
||||
mode: "0644"
|
||||
force: true
|
||||
|
||||
- name: Determine deb arch for Docker repo
|
||||
ansible.builtin.set_fact:
|
||||
docker_deb_arch: >-
|
||||
{{ 'arm64' if ansible_architecture in ['aarch64', 'arm64'] else 'amd64' }}
|
||||
|
||||
- name: Add Docker apt repository
|
||||
ansible.builtin.apt_repository:
|
||||
repo: >-
|
||||
deb [arch={{ docker_deb_arch }} signed-by=/etc/apt/keyrings/docker.asc]
|
||||
https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable
|
||||
filename: docker
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Install Docker Engine and Compose plugin
|
||||
ansible.builtin.apt:
|
||||
name:
|
||||
- docker-ce
|
||||
- docker-ce-cli
|
||||
- containerd.io
|
||||
- docker-buildx-plugin
|
||||
- docker-compose-plugin
|
||||
state: present
|
||||
|
||||
- name: Enable and start Docker
|
||||
ansible.builtin.service:
|
||||
name: docker
|
||||
state: started
|
||||
enabled: true
|
||||
|
||||
- name: Add users to docker group
|
||||
ansible.builtin.user:
|
||||
name: "{{ item }}"
|
||||
groups: docker
|
||||
append: true
|
||||
loop: "{{ docker_users | default([]) }}"
|
||||
ignore_errors: true
|
||||
|
||||
# --- Deploy docker-compose app and start services ---
|
||||
- name: Ensure app root exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ app_root }}"
|
||||
state: directory
|
||||
mode: "0755"
|
||||
|
||||
- name: Copy docker-compose.yaml to host
|
||||
ansible.builtin.copy:
|
||||
src: "{{ playbook_dir }}/../../docker-compose.yaml"
|
||||
dest: "{{ app_root }}/docker-compose.yaml"
|
||||
mode: "0644"
|
||||
|
||||
- name: Render .env file
|
||||
ansible.builtin.template:
|
||||
src: ../templates/env.j2
|
||||
dest: "{{ app_root }}/.env"
|
||||
mode: "0600"
|
||||
|
||||
- name: Pull images
|
||||
ansible.builtin.command: docker compose -f {{ app_root }}/docker-compose.yaml pull
|
||||
args:
|
||||
chdir: "{{ app_root }}"
|
||||
|
||||
- name: Start services
|
||||
ansible.builtin.command: docker compose -f {{ app_root }}/docker-compose.yaml up -d
|
||||
args:
|
||||
chdir: "{{ app_root }}"
|
||||
5
ansible/requirements.yml
Normal file
5
ansible/requirements.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
collections:
|
||||
- name: community.general
|
||||
- name: google.cloud
|
||||
- name: community.docker
|
||||
1
ansible/templates/cloudflare.ini.j2
Normal file
1
ansible/templates/cloudflare.ini.j2
Normal file
@@ -0,0 +1 @@
|
||||
dns_cloudflare_api_token = {{ cloudflare_api_token }}
|
||||
8
ansible/templates/env.j2
Normal file
8
ansible/templates/env.j2
Normal file
@@ -0,0 +1,8 @@
|
||||
GCS_KEY_ENCODED={{ gcs_key_encoded }}
|
||||
HOOK_TOKEN={{ hook_token }}
|
||||
HOOK_URI={{ hook_uri }}
|
||||
REDIS_PASSWORD={{ redis_password }}
|
||||
REDISCLOUD_URL={{ rediscloud_url }}
|
||||
REPLREG_HOST={{ replreg_host }}
|
||||
REPLREG_SECRET={{ replreg_secret }}
|
||||
REGISTRY_URL={{ registry_url }}
|
||||
47
ansible/templates/nginx_site.conf.j2
Normal file
47
ansible/templates/nginx_site.conf.j2
Normal file
@@ -0,0 +1,47 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name {{ domain_name }};
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name {{ domain_name }};
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/{{ domain_name }}/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/{{ domain_name }}/privkey.pem;
|
||||
ssl_session_timeout 1d;
|
||||
ssl_session_cache shared:SSL:10m;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
|
||||
|
||||
root /var/www/{{ domain_name }}/html;
|
||||
index index.htm index.html;
|
||||
|
||||
# Static site
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# Block listing catalog
|
||||
location ~ v2/_catalog$ {
|
||||
return 401;
|
||||
}
|
||||
|
||||
# Docker Registry proxy
|
||||
location /v2 {
|
||||
client_max_body_size 10000m;
|
||||
client_body_timeout 3600s;
|
||||
proxy_connect_timeout 300s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_read_timeout 3600s;
|
||||
send_timeout 3600s;
|
||||
proxy_pass http://127.0.0.1:5000;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
}
|
||||
@@ -69,26 +69,6 @@ services:
|
||||
- ./redis/data:/data
|
||||
command: redis-server --requirepass ${REDIS_PASSWORD}
|
||||
|
||||
nginx:
|
||||
image: us-east4-docker.pkg.dev/rgstry/ttl-sh-nginx/nginx:latest
|
||||
build:
|
||||
context: nginx
|
||||
dockerfile: Dockerfile
|
||||
platforms:
|
||||
- "linux/amd64"
|
||||
container_name: ttlsh-nginx
|
||||
restart: always
|
||||
pull_policy: always
|
||||
environment:
|
||||
- PORT=80
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
depends_on:
|
||||
- registry
|
||||
networks:
|
||||
- ttlsh-network
|
||||
|
||||
networks:
|
||||
ttlsh-network:
|
||||
driver: bridge
|
||||
|
||||
27
install.sh
27
install.sh
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
REMOTE_HOST=178.156.198.215
|
||||
REMOTE_USER=root
|
||||
INSTALL_DIR=/opt/ttlsh
|
||||
|
||||
function setup_docker_compose() {
|
||||
ssh $REMOTE_USER@$REMOTE_HOST "mkdir -p $INSTALL_DIR"
|
||||
scp docker-compose.yaml $REMOTE_USER@$REMOTE_HOST:$INSTALL_DIR/docker-compose.yaml
|
||||
}
|
||||
|
||||
function setup_provisioner_script() {
|
||||
scp provision.sh $REMOTE_USER@$REMOTE_HOST:$INSTALL_DIR/provision.sh
|
||||
ssh $REMOTE_USER@$REMOTE_HOST "chmod a+x $INSTALL_DIR/provision.sh"
|
||||
}
|
||||
|
||||
function run_provisioner_script() {
|
||||
ssh $REMOTE_USER@$REMOTE_HOST "bash $INSTALL_DIR/provision.sh $1"
|
||||
}
|
||||
|
||||
function install() {
|
||||
setup_docker_compose
|
||||
setup_provisioner_script
|
||||
run_provisioner_script $DOPPLER_TOKEN
|
||||
}
|
||||
|
||||
install
|
||||
@@ -1,12 +0,0 @@
|
||||
FROM nginx:latest
|
||||
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
COPY src/favicon.ico /usr/share/nginx/html/
|
||||
COPY src/index.htm /usr/share/nginx/html/
|
||||
COPY src/ttlsh_files /usr/share/nginx/html/ttlsh_files/
|
||||
|
||||
ADD entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
@@ -1,7 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
sed -i "s/__PORT__/$PORT/g" /etc/nginx/nginx.conf
|
||||
|
||||
exec "$@"
|
||||
@@ -1,39 +0,0 @@
|
||||
events {}
|
||||
http {
|
||||
include mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
upstream registry {
|
||||
server ttlsh-registry:5000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen __PORT__;
|
||||
server_name _;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/html;
|
||||
index index.htm;
|
||||
}
|
||||
|
||||
location ~ v2/_catalog$ {
|
||||
return 401;
|
||||
}
|
||||
|
||||
location /v2 {
|
||||
client_max_body_size 10000m;
|
||||
client_body_timeout 3600s;
|
||||
proxy_connect_timeout 300s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_read_timeout 3600s;
|
||||
send_timeout 3600s;
|
||||
proxy_pass http://registry;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_request_buffering off;
|
||||
}
|
||||
}
|
||||
}
|
||||
94
provision.sh
94
provision.sh
@@ -1,94 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
DOPPLER_TOKEN=$1
|
||||
|
||||
function setup_doppler() {
|
||||
# install for ubuntu: https://docs.doppler.com/docs/cli
|
||||
sudo apt-get update && sudo apt-get install -y apt-transport-https ca-certificates curl gnupg
|
||||
curl -sLf --retry 3 --tlsv1.2 --proto "=https" 'https://packages.doppler.com/public/cli/gpg.DE2A7741A397C129.key' | sudo gpg --dearmor -o /usr/share/keyrings/doppler-archive-keyring.gpg
|
||||
echo "deb [signed-by=/usr/share/keyrings/doppler-archive-keyring.gpg] https://packages.doppler.com/public/cli/deb/debian any-version main" | sudo tee /etc/apt/sources.list.d/doppler-cli.list
|
||||
sudo apt-get update && sudo apt-get install doppler
|
||||
|
||||
# authenticate with service token
|
||||
echo $DOPPLER_TOKEN | doppler configure set token --scope /
|
||||
}
|
||||
|
||||
setup_docker() {
|
||||
# Adapted from:
|
||||
# * https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository
|
||||
|
||||
# Add Docker's official GPG key:
|
||||
sudo apt-get update
|
||||
sudo apt-get install ca-certificates curl
|
||||
sudo install -m 0755 -d /etc/apt/keyrings
|
||||
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
|
||||
sudo chmod a+r /etc/apt/keyrings/docker.asc
|
||||
|
||||
# Add the repository to Apt sources:
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
|
||||
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
sudo apt-get update
|
||||
|
||||
# install necessary packages
|
||||
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
|
||||
}
|
||||
|
||||
setup_gcloud() {
|
||||
# Adapted from:
|
||||
# * https://cloud.google.com/sdk/docs/downloads-interactive
|
||||
# * Artifact Registry setup commands
|
||||
|
||||
INSTALL_PATH="$(doppler secrets get GOOGLE_APPLICATION_CREDENTIALS --plain)"
|
||||
INSTALL_EMAIL="$(doppler secrets get GOOGLE_APPLICATION_CREDENTIALS_EMAIL --plain)"
|
||||
REGISTRY_URI="$(doppler secrets get GOOGLE_CLOUD_ARTIFACT_REGISTRY_URI --plain)"
|
||||
|
||||
mkdir -p "$(dirname "$INSTALL_PATH")"
|
||||
doppler secrets get GOOGLE_APPLICATION_CREDENTIALS_JSON --plain >"$INSTALL_PATH"
|
||||
chmod 600 "$INSTALL_PATH"
|
||||
|
||||
echo "export GOOGLE_APPLICATION_CREDENTIALS=\"$INSTALL_PATH\"" >> "$HOME/.bashrc"
|
||||
|
||||
# download the installer
|
||||
curl https://sdk.cloud.google.com | bash
|
||||
|
||||
# Explicitly add gcloud to PATH for this session
|
||||
export PATH="$HOME/google-cloud-sdk/bin:$PATH"
|
||||
|
||||
gcloud auth activate-service-account "$INSTALL_EMAIL" --key-file="$INSTALL_PATH" --quiet
|
||||
gcloud auth configure-docker "$REGISTRY_URI" --quiet
|
||||
}
|
||||
|
||||
setup_ttlsh_env() {
|
||||
for VAR in \
|
||||
GCS_KEY_ENCODED \
|
||||
HOOK_TOKEN \
|
||||
HOOK_URI \
|
||||
REDIS_PASSWORD \
|
||||
REDISCLOUD_URL \
|
||||
REPLREG_HOST \
|
||||
REPLREG_SECRET \
|
||||
REGISTRY_URL
|
||||
do
|
||||
echo "$VAR=$(doppler secrets get "$VAR" --plain)" >> /opt/ttlsh/.env
|
||||
done
|
||||
|
||||
chmod 600 "$ENV_FILE"
|
||||
}
|
||||
|
||||
function run_ttlsh()
|
||||
{
|
||||
docker compose -f /opt/ttlsh/docker-compose.yaml pull
|
||||
docker compose -f /opt/ttlsh/docker-compose.yaml up -d
|
||||
}
|
||||
|
||||
function provision() {
|
||||
setup_doppler
|
||||
setup_docker
|
||||
setup_gcloud
|
||||
setup_ttlsh_env
|
||||
run_ttlsh
|
||||
}
|
||||
|
||||
provision
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user