From 24725519533cebb3e6eae4ec83be0f57412cea7c Mon Sep 17 00:00:00 2001 From: Reckless_Satoshi Date: Thu, 11 Jan 2024 12:16:13 +0000 Subject: [PATCH] Add simple web hosted federated client --- .github/workflows/frontend-build.yml | 10 +- .github/workflows/release.yml | 11 ++- ...-image.yml => selfhosted-client-image.yml} | 2 +- .github/workflows/web-client-image.yml | 94 +++++++++++++++++++ .../src/components/HostAlert/UnsafeAlert.tsx | 2 + web/Dockerfile | 26 +++++ web/basic.html | 60 ++++++++++++ web/nginx.conf | 58 ++++++++++++ web/pro.html | 62 ++++++++++++ web/readme.md | 5 + 10 files changed, 325 insertions(+), 5 deletions(-) rename .github/workflows/{client-image.yml => selfhosted-client-image.yml} (98%) create mode 100644 .github/workflows/web-client-image.yml create mode 100644 web/Dockerfile create mode 100644 web/basic.html create mode 100644 web/nginx.conf create mode 100644 web/pro.html create mode 100644 web/readme.md diff --git a/.github/workflows/frontend-build.yml b/.github/workflows/frontend-build.yml index fba81d465..ae8651a99 100644 --- a/.github/workflows/frontend-build.yml +++ b/.github/workflows/frontend-build.yml @@ -91,9 +91,15 @@ jobs: with: workflow: 'Docker: Coordinator' token: ${{ secrets.PERSONAL_TOKEN }} - - name: 'Invoke Client App Build CI/CD workflow' + - name: 'Invoke Selfhosted Client App Build CI/CD workflow' if: inputs.semver == '' uses: benc-uk/workflow-dispatch@v121 with: - workflow: 'Docker: Client' + workflow: 'Docker: Selfhosted Client' + token: ${{ secrets.PERSONAL_TOKEN }} + - name: 'Invoke Web Client App Build CI/CD workflow' + if: inputs.semver == '' + uses: benc-uk/workflow-dispatch@v121 + with: + workflow: 'Docker: Web Client' token: ${{ secrets.PERSONAL_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6b58063a4..f0394d71a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,8 +55,15 @@ jobs: with: semver: ${{ needs.check-versions.outputs.semver }} - client-image: - uses: RoboSats/robosats/.github/workflows/client-image.yml@main + selfhosted-client-image: + uses: RoboSats/robosats/.github/workflows/selfhosted-client-image.yml@main + needs: frontend-build + secrets: inherit + with: + semver: ${{ needs.check-versions.outputs.semver }} + + web-client-image: + uses: RoboSats/robosats/.github/workflows/web-client-image.yml@main needs: frontend-build secrets: inherit with: diff --git a/.github/workflows/client-image.yml b/.github/workflows/selfhosted-client-image.yml similarity index 98% rename from .github/workflows/client-image.yml rename to .github/workflows/selfhosted-client-image.yml index 1f0f63769..3d62869e0 100644 --- a/.github/workflows/client-image.yml +++ b/.github/workflows/selfhosted-client-image.yml @@ -1,4 +1,4 @@ -name: "Docker: Client" +name: 'Docker: Selfhosted Client' on: workflow_dispatch: diff --git a/.github/workflows/web-client-image.yml b/.github/workflows/web-client-image.yml new file mode 100644 index 000000000..ecac26748 --- /dev/null +++ b/.github/workflows/web-client-image.yml @@ -0,0 +1,94 @@ +name: 'Docker: Web Client' + +on: + workflow_dispatch: + workflow_call: + inputs: + semver: + required: true + type: string + push: + branches: [ "main" ] + paths: ["frontend", "web"] + pull_request: + branches: [ "main" ] + paths: ["frontend", "web"] + +jobs: + push_to_registry: + name: 'Push Docker image to Docker Hub' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: 'Copy Static' # Needed since Github actions does not support symlinks + run: cp -r frontend/static nodeapp/static + + - name: 'Download main.js Artifact' + if: inputs.semver == '' # Only if workflow fired from frontend-build.yml + uses: dawidd6/action-download-artifact@v3 + with: + workflow: frontend-build.yml + workflow_conclusion: success + name: web-main-js + path: nodeapp/static/frontend/ + + - name: 'Download main.js Artifact for a release' + if: inputs.semver != '' # Only if fired as job in release.yml + uses: actions/download-artifact@v4 + with: + name: web-main-js + path: nodeapp/static/frontend/ + + - name: 'Download pro.js Artifact' + if: inputs.semver == '' # Only if workflow fired from frontend-build.yml + uses: dawidd6/action-download-artifact@v3 + with: + workflow: frontend-build.yml + workflow_conclusion: success + name: web-pro-js + path: nodeapp/static/frontend/ + + - name: 'Download pro.js Artifact for a release' + if: inputs.semver != '' # Only if fired as job in release.yml + uses: actions/download-artifact@v4 + with: + name: web-pro-js + path: nodeapp/static/frontend/ + + - name: 'Log in to Docker Hub' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: 'Extract metadata (tags, labels) for Docker' + id: meta + uses: docker/metadata-action@v5 + with: + images: recksato/robosats-web + tags: | + type=ref,event=pr + type=ref,event=tag + type=semver,pattern={{major}}.{{minor}} + type=sha,enable=true,priority=100,prefix=,suffix=,format=short + type=raw,value=latest + + - name: 'Get Commit Hash' + id: commit + uses: pr-mpt/actions-commit-hash@v3 + + - name: 'Set up QEMU' + uses: docker/setup-qemu-action@v3 + + - name: 'Set up Docker Buildx' + uses: docker/setup-buildx-action@v3 + + - name: 'Build and push Docker image' + uses: docker/build-push-action@v5 + with: + context: ./nodeapp + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/frontend/src/components/HostAlert/UnsafeAlert.tsx b/frontend/src/components/HostAlert/UnsafeAlert.tsx index 92fec5cb4..dd143e4e8 100644 --- a/frontend/src/components/HostAlert/UnsafeAlert.tsx +++ b/frontend/src/components/HostAlert/UnsafeAlert.tsx @@ -24,6 +24,8 @@ function federationUrls(): string[] { } } + // web hosted frontend without coordinator + urls.push('robodexarjwtfryec556cjdz3dfa7u47saek6lkftnkgshvgg2kcumqd.onion'); return urls; } diff --git a/web/Dockerfile b/web/Dockerfile new file mode 100644 index 000000000..5b4a207ca --- /dev/null +++ b/web/Dockerfile @@ -0,0 +1,26 @@ +FROM alpine:3.18.0 + +LABEL maintainer="Reckless_Satoshi https://github.com/reckless-satoshi" + +# Needs a copy or symlink of /frontend/static in /nodeapp/static +# Github client release workflow copies /frontend/static here + +RUN mkdir -p /usr/src/robosats +WORKDIR /usr/src/robosats + +RUN set -x \ + && addgroup -g 101 -S nginx \ + && adduser -S -D -H -u 101 -h /var/cache/nginx -s /sbin/nologin -G nginx -g nginx nginx + +COPY . . +COPY ./nginx.conf /etc/nginx/nginx.conf +COPY ./coordinators/ /etc/nginx/conf.d/ + +RUN apk -U --no-cache upgrade \ + && apk --no-cache add socat \ + && apk --no-cache add nginx + +EXPOSE 12596 +HEALTHCHECK CMD curl --fail http://localhost:12596/selfhosted || exit 1 + +CMD ["sh", "robosats-client.sh"] \ No newline at end of file diff --git a/web/basic.html b/web/basic.html new file mode 100644 index 000000000..99baef715 --- /dev/null +++ b/web/basic.html @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + RoboSats - Simple and Private Bitcoin Exchange + + + + + + + + +
+
+
+
+
+
+
+
    +
  • +
    Looking for robot parts ...
    +
  • +
  • +
    Adding layers to the onion ...
    +
  • +
  • +
    Winning at game theory ...
    +
  • +
  • +
    Moving Sats at light speed ...
    +
  • +
  • +
    Hiding in 2^256 bits of entropy...
    +
  • +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/web/nginx.conf b/web/nginx.conf new file mode 100644 index 000000000..85f78c4dd --- /dev/null +++ b/web/nginx.conf @@ -0,0 +1,58 @@ +daemon off; + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + +events { + worker_connections 1024; +} + +http { + + include /etc/nginx/mime.types; + default_type application/octet-stream; + large_client_header_buffers 4 64K; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /dev/stdout main; + error_log /dev/stderr warn; + + sendfile on; + keepalive_timeout 65; + + server { + + listen 12596; + server_name robosats_client; + + # add_header Access-Control-Allow-Headers "*"; + # add_header Access-Control-Allow-Origin "*"; + + location / { + root /usr/src/robosats; + try_files $uri $uri/ /basic.html; + index basic.html; + } + + location /pro { + root /usr/src/robosats; + try_files $uri $uri/ /pro.html; + index pro.html; + } + + location /static/ { + alias /usr/src/robosats/static/; + autoindex on; + } + + location = /favicon.ico { + alias /usr/src/robosats/static/assets/images/favicon-96x96.png; + } + } +} \ No newline at end of file diff --git a/web/pro.html b/web/pro.html new file mode 100644 index 000000000..242922892 --- /dev/null +++ b/web/pro.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + RoboSats PRO - Simple and Private Bitcoin Exchange + + + + + + + + + + +
+
+
+
+
+
+
+
    +
  • +
    Looking for robot parts ...
    +
  • +
  • +
    Adding layers to the onion ...
    +
  • +
  • +
    Winning at game theory ...
    +
  • +
  • +
    Moving Sats at light speed ...
    +
  • +
  • +
    Hiding in 2^256 bits of entropy...
    +
  • +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/web/readme.md b/web/readme.md new file mode 100644 index 000000000..5124f1564 --- /dev/null +++ b/web/readme.md @@ -0,0 +1,5 @@ +# Host a RoboSat web client + +This docker app is intended for hosting a web client for public use. + +Similar to `/nodeapp`, but does not use the selfhosted flags nor torify connections to coordinators. The browser itself must support Tor. \ No newline at end of file