From ad6788639e0de01196f91055aae1251dfb781d44 Mon Sep 17 00:00:00 2001 From: CJ_Clippy Date: Fri, 21 Feb 2025 19:33:39 -0800 Subject: [PATCH] remove submodule --- .gitea/workflows/builder.yaml | 65 ++----- .gitea/workflows/tests.yaml | 34 ++-- .gitmodules | 3 - apps/aquatic-tracker | 1 - apps/bright/config/runtime.exs | 6 +- .../lib/bright/oban_workers/create_torrent.ex | 4 +- apps/bright/lib/bright/tracker.ex | 75 ++++----- apps/tracker-helper/Dockerfile | 56 +++++++ .../root/etc/aquatic/config.toml | 27 +++ apps/tracker-helper/root/etc/caddy/Caddyfile | 18 ++ .../root/etc/s6-overlay/s6-rc.d/aquatic/run | 3 + .../root/etc/s6-overlay/s6-rc.d/aquatic/type | 1 + .../s6-rc.d/caddy/dependencies.d/aquatic | 0 .../root/etc/s6-overlay/s6-rc.d/caddy/run | 3 + .../root/etc/s6-overlay/s6-rc.d/caddy/type | 1 + .../tracker-helper/dependencies.d/aquatic | 0 .../etc/s6-overlay/s6-rc.d/tracker-helper/run | 7 + .../s6-overlay/s6-rc.d/tracker-helper/type | 1 + .../s6-rc.d/user/contents.d/aquatic | 0 .../s6-rc.d/user/contents.d/tracker-helper | 0 .../root/etc/tracker/healthcheck.sh | 5 + .../root/usr/src/tracker-helper/.gitkeep | 0 .../root/var/lib/aquatic/accesslist | 0 config/deploy.yml | 45 ++--- docker-compose.yml | 32 ---- services/tracker-helper/test/app.test.ts | 158 ------------------ services/tracker-helper/test/fixtures/taco | 4 + .../{tracker-helper => tracker}/.dockerignore | 0 .../{tracker-helper => tracker}/.gitignore | 0 .../{tracker-helper => tracker}/Dockerfile | 4 +- .../{tracker-helper => tracker}/README.md | 0 services/{tracker-helper => tracker}/app.ts | 32 ++-- .../{tracker-helper => tracker}/bun.lockb | Bin .../fifo-helper.ts | 0 services/{tracker-helper => tracker}/index.ts | 0 .../{tracker-helper => tracker}/package.json | 0 .../pnpm-lock.yaml | 0 services/tracker/test/app.test.ts | 156 +++++++++++++++++ .../test/fixtures/whitelist | 0 .../{tracker-helper => tracker}/tsconfig.json | 0 40 files changed, 373 insertions(+), 368 deletions(-) delete mode 100644 .gitmodules delete mode 160000 apps/aquatic-tracker create mode 100644 apps/tracker-helper/Dockerfile create mode 100644 apps/tracker-helper/root/etc/aquatic/config.toml create mode 100644 apps/tracker-helper/root/etc/caddy/Caddyfile create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/run create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/type create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/dependencies.d/aquatic create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/run create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/type create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/dependencies.d/aquatic create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/run create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/type create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/aquatic create mode 100644 apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/tracker-helper create mode 100755 apps/tracker-helper/root/etc/tracker/healthcheck.sh create mode 100644 apps/tracker-helper/root/usr/src/tracker-helper/.gitkeep create mode 100644 apps/tracker-helper/root/var/lib/aquatic/accesslist delete mode 100644 services/tracker-helper/test/app.test.ts create mode 100644 services/tracker-helper/test/fixtures/taco rename services/{tracker-helper => tracker}/.dockerignore (100%) rename services/{tracker-helper => tracker}/.gitignore (100%) rename services/{tracker-helper => tracker}/Dockerfile (88%) rename services/{tracker-helper => tracker}/README.md (100%) rename services/{tracker-helper => tracker}/app.ts (74%) rename services/{tracker-helper => tracker}/bun.lockb (100%) rename services/{tracker-helper => tracker}/fifo-helper.ts (100%) rename services/{tracker-helper => tracker}/index.ts (100%) rename services/{tracker-helper => tracker}/package.json (100%) rename services/{tracker-helper => tracker}/pnpm-lock.yaml (100%) create mode 100644 services/tracker/test/app.test.ts rename services/{tracker-helper => tracker}/test/fixtures/whitelist (100%) rename services/{tracker-helper => tracker}/tsconfig.json (100%) diff --git a/.gitea/workflows/builder.yaml b/.gitea/workflows/builder.yaml index 75bd1e3..30c4dd1 100644 --- a/.gitea/workflows/builder.yaml +++ b/.gitea/workflows/builder.yaml @@ -19,19 +19,6 @@ jobs: with: submodules: recursive - # IDK if I need this - # - name: Set docker metadata - # id: meta - # uses: docker/metadata-action@v5 - # with: - # images: | - # gitea.futureporn.net/futureporn/tracker-helper:latest - # tags: | - # type=ref,event=branch - # type=ref,event=pr - # type=semver,pattern={{version}} - # type=semver,pattern={{major}}.{{minor}} - - name: Login to Gitea Docker Registry uses: docker/login-action@v3 with: @@ -39,31 +26,30 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - - name: Build futureporn/tracker-helper - uses: docker/build-push-action@v6 - with: - context: ./services/tracker-helper - push: true - tags: gitea.futureporn.net/futureporn/tracker-helper:latest - labels: | - org.opencontainers.image.description=Opentracker helper service. Adds info_hash whitelisting via HTTP - org.opencontainers.image.title=tracker-helper - org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}} - org.opencontainers.image.licenses=unlicense - org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp - org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/tracker-helper - secrets: | - WL_USERNAME=${{ secrets.WL_USERNAME }} - WL_PASSWORD=${{ secrets.WL_PASSWORD }} - - name: Build futureporn/aquatic uses: docker/build-push-action@v6 with: - context: ./apps/aquatic-tracker - file: ./apps/aquatic-tracker/docker/aquatic_udp.Dockerfile + context: ./apps/aquatic + file: ./apps/aquatic/docker/aquatic_udp.Dockerfile push: true tags: gitea.futureporn.net/futureporn/aquatic:latest + - name: Build futureporn/tracker + uses: docker/build-push-action@v6 + with: + context: ./services/tracker + push: true + tags: gitea.futureporn.net/futureporn/tracker:latest + labels: | + org.opencontainers.image.description=Aquatic tracker with custom helper service, adding info_hash accesslist operations via HTTP + org.opencontainers.image.title=tracker + org.opencontainers.image.licenses=unlicense + org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp + org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/tracker + secrets: | + TRACKER_HELPER_USERNAME=${{ secrets.TRACKER_HELPER_USERNAME }} + TRACKER_HELPER_PASSWORD=${{ secrets.TRACKER_HELPER_PASSWORD }} + - name: Build futureporn/bright uses: docker/build-push-action@v6 with: @@ -80,18 +66,3 @@ jobs: org.opencontainers.image.licenses=unlicense org.opencontainers.image.source=https://gitea.futureporn.net/futureporn/fp org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/bright - - # - name: Build futureporn/opentracker - # uses: docker/build-push-action@v6 - # with: - # context: ./apps/opentracker - # push: true - # tags: gitea.futureporn.net/futureporn/opentracker:latest - # labels: | - # org.opencontainers.image.description=opentracker is an open and free bittorrent tracker project. - # org.opencontainers.image.title=opentracker - # org.opencontainers.image.created={{commit_date 'YYYY-MM-DDTHH:mm:ss.SSS[Z]'}} - # org.opencontainers.image.version={{version}} - # org.opencontainers.image.licenses=beerware - # org.opencontainers.image.source=https://erdgeist.org/arts/software/opentracker - # org.opencontainers.image.url=https://gitea.futureporn.net/futureporn/-/packages/container/opentracker diff --git a/.gitea/workflows/tests.yaml b/.gitea/workflows/tests.yaml index 43cd707..ab15f0e 100644 --- a/.gitea/workflows/tests.yaml +++ b/.gitea/workflows/tests.yaml @@ -34,9 +34,9 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} PUBLIC_S3_ENDPOINT: ${{ vars.PUBLIC_S3_ENDPOINT }} SITE_URL: https://futureporn.net - WL_URL: ${{ vars.WL_URL }} - WL_USERNAME: ${{ secrets.WL_USERNAME }} - WL_PASSWORD: ${{ secrets.WL_PASSWORD }} + TRACKER_HELPER_URL: ${{ vars.TRACKER_HELPER_URL }} + TRACKER_HELPER_USERNAME: ${{ secrets.TRACKER_HELPER_USERNAME }} + TRACKER_HELPER_PASSWORD: ${{ secrets.TRACKER_HELPER_PASSWORD }} DB_NAME: ${{ vars.DB_NAME }} DB_HOST: ${{ vars.DB_HOST }} DB_PORT: ${{ vars.DB_PORT }} @@ -72,29 +72,17 @@ jobs: --health-timeout 5s --health-retries 5 - tracker-helper: - image: gitea.futureporn.net/futureporn/tracker-helper:latest + tracker: + image: gitea.futureporn.net/futureporn/tracker:latest ports: - 5063:5063 - env: - WL_FILE_PATH: /var/lib/aquatic/whitelist - WL_USERNAME: ${{ secrets.WL_USERNAME }} - WL_PASSWORD: ${{ secrets.WL_PASSWORD }} - WL_PORT: 5063 - volumes: - - aquatic:/var/lib/aquatic - - /tmp/aquatic:/tmp/aquatic - - /tmp/test:/root/test - - /test2:/root/test2 - - aquatic: - image: gitea.futureporn.net/futureporn/aquatic:latest - ports: - 3003:3003 - 9000:9000 - volumes: - - aquatic:/var/lib/aquatic env: + TRACKER_HELPER_ACCESSLIST_PATH: /var/lib/aquatic/whitelist + TRACKER_HELPER_USERNAME: ${{ secrets.TRACKER_HELPER_USERNAME }} + TRACKER_HELPER_PASSWORD: ${{ secrets.TRACKER_HELPER_PASSWORD }} + TRACKER_HELPER_PORT: 5063 ACCESS_LIST_CONTENTS: "" CONFIG_FILE_CONTENTS: | log_level = 'debug' @@ -105,12 +93,12 @@ jobs: address_ipv6 = "[::]:3003" [statistics] interval = 5 - print_to_stdout = true + print_to_stdout = false run_prometheus_endpoint = true prometheus_endpoint_address = "0.0.0.0:9000" [access_list] mode = "allow" - path = "/var/lib/aquatic/whitelist" + path = "/var/lib/aquatic/accesslist" [privileges] # Chroot and switch group and user after binding to sockets drop_privileges = true diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f2d5550..0000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "apps/aquatic-tracker"] - path = apps/aquatic-tracker - url = https://github.com/insanity54/aquatic diff --git a/apps/aquatic-tracker b/apps/aquatic-tracker deleted file mode 160000 index 96e6975..0000000 --- a/apps/aquatic-tracker +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 96e69754510c82ad2bbb9d0a2967c8bca0696bbd diff --git a/apps/bright/config/runtime.exs b/apps/bright/config/runtime.exs index 9bdc8a3..b4f96e3 100644 --- a/apps/bright/config/runtime.exs +++ b/apps/bright/config/runtime.exs @@ -32,9 +32,9 @@ config :bright, config :bright, :torrent, tracker_url: System.get_env("TRACKER_URL"), - whitelist_url: System.get_env("WL_URL"), - whitelist_username: System.get_env("WL_USERNAME"), - whitelist_password: System.get_env("WL_PASSWORD") + tracker_helper_url: System.get_env("TRACKER_HELPER_URL"), + tracker_helper_username: System.get_env("TRACKER_HELPER_USERNAME"), + tracker_helper_password: System.get_env("TRACKER_HELPER_PASSWORD") config :bright, :buckets, media: System.get_env("AWS_BUCKET") diff --git a/apps/bright/lib/bright/oban_workers/create_torrent.ex b/apps/bright/lib/bright/oban_workers/create_torrent.ex index 847af31..496ff28 100644 --- a/apps/bright/lib/bright/oban_workers/create_torrent.ex +++ b/apps/bright/lib/bright/oban_workers/create_torrent.ex @@ -26,8 +26,8 @@ defmodule Bright.ObanWorkers.CreateTorrent do cdn_url: cdn_url, magnet: tf.magnet }), - {_, _} <- Tracker.whitelist_info_hash(torrent.info_hash_v1), - {_, _} <- Tracker.whitelist_info_hash(torrent.info_hash_v2), + {_, _} <- Tracker.accesslist_info_hash(torrent.info_hash_v1), + {_, _} <- Tracker.accesslist_info_hash(torrent.info_hash_v2), {:ok, _updated_vod} <- Streams.update_vod(vod, %{}) do {:ok, torrent} end diff --git a/apps/bright/lib/bright/tracker.ex b/apps/bright/lib/bright/tracker.ex index 1a521bf..d028348 100644 --- a/apps/bright/lib/bright/tracker.ex +++ b/apps/bright/lib/bright/tracker.ex @@ -13,72 +13,55 @@ defmodule Bright.Tracker do end @doc """ - get the URL to our Bittorrent tracker accesslist URL, which is part of our opentracker docker container. - This is where we send infohashes that end up in opentracker's adder.fifo - Usually it's port 8666, path /whitelist + get the URL to our tracker helper accesslist URL, which is part of our tracker docker container. + This is where we send infohashes that end up in aquatic's accesslist + Usually it's port 5063, path /accesslist """ - @spec whitelist_url() :: binary() - def whitelist_url do + @spec accesslist_url() :: binary() + def accesslist_url do url = - case Application.fetch_env!(:bright, :torrent)[:whitelist_url] do - nil -> raise "whitelist_url missing or empty in app config" - "" -> raise "whitelist_url missing or empty in app config" + case Application.fetch_env!(:bright, :torrent)[:tracker_helper_accesslist_url] do + nil -> raise "accesslist_url missing or empty in app config" + "" -> raise "accesslist_url missing or empty in app config" url -> url end - Logger.debug("whitelist_url=#{url}") + Logger.debug("accesslist_url=#{url}") url end - @spec whitelist_username() :: binary() - def whitelist_username do - case Application.fetch_env!(:bright, :torrent)[:whitelist_username] do - nil -> raise "whitelist_username missing or empty in app config" - "" -> raise "whitelist_username missing or empty in app config" + @spec tracker_helper_username() :: binary() + def tracker_helper_username do + case Application.fetch_env!(:bright, :torrent)[:tracker_helper_username] do + nil -> raise "tracker_helper_username missing or empty in app config" + "" -> raise "tracker_helper_username missing or empty in app config" username -> username end end - @spec whitelist_password() :: binary() - def whitelist_password do - case Application.fetch_env!(:bright, :torrent)[:whitelist_password] do - nil -> raise "whitelist_password missing or empty in app config" - "" -> raise "whitelist_password missing or empty in app config" + @spec tracker_helper_password() :: binary() + def tracker_helper_password do + case Application.fetch_env!(:bright, :torrent)[:tracker_helper_password] do + nil -> raise "tracker_helper_password missing or empty in app config" + "" -> raise "tracker_helper_password missing or empty in app config" password -> password end end - @spec whitelist_feed_url() :: binary() - def whitelist_feed_url do - case Application.fetch_env!(:bright, :torrent)[:whitelist_feed_url] do - nil -> raise "whitelist_feed_url missing or empty in app config" - "" -> raise "whitelist_feed_url missing or empty in app config" - feed_url -> feed_url - end - end - - def whitelist_info_hash(info_hash) do - whitelist_url = whitelist_url() - username = whitelist_username() - password = whitelist_password() + def accesslist_info_hash(info_hash) do + accesslist_url = accesslist_url() + username = tracker_helper_username() + password = tracker_helper_password() Logger.debug( - "Attempting to whitelist info_hash=#{info_hash}, whitelist_url=#{whitelist_url}, whitelist_username=#{username}, whitelist_password=#{password}" + "Attempting to accesslist info_hash=#{info_hash}, accesslist_url=#{accesslist_url}, tracker_helper_username=#{username}, tracker_helper_password=#{password}" ) - send_whitelist_request(whitelist_url, info_hash, username, password) - # case URI.parse(whitelist_url) do - # %URI{scheme: scheme, host: host, port: port} when host not in [nil, ""] and port != nil -> - # full_url = "#{scheme}://#{host}:#{port}" - - # _ -> - # Logger.error("Invalid whitelist_url: #{whitelist_url}") - # {:error, :invalid_url} - # end + send_accesslist_request(accesslist_url, info_hash, username, password) end - defp send_whitelist_request(url, info_hash, username, password) do - Logger.debug("send_whitelist_request to url=#{url}") + defp send_accesslist_request(url, info_hash, username, password) do + Logger.debug("send_accesslist_request to url=#{url}") headers = [ {"Content-Type", "text/plain"}, @@ -87,12 +70,12 @@ defmodule Bright.Tracker do case HTTPoison.post(url, info_hash, headers) do {:ok, %HTTPoison.Response{status_code: 201, body: response_body}} -> - Logger.info("Successfully whitelisted info_hash=#{info_hash}") + Logger.info("Successfully accesslisted info_hash=#{info_hash}") {:ok, response_body} {:ok, %HTTPoison.Response{status_code: status_code, body: error_body}} -> Logger.warning( - "Whitelist failed: info_hash=#{info_hash}, status=#{status_code}, error=#{error_body}" + "accesslist failed: info_hash=#{info_hash}, status=#{status_code}, error=#{error_body}" ) {:error, %{status: status_code, body: error_body}} diff --git a/apps/tracker-helper/Dockerfile b/apps/tracker-helper/Dockerfile new file mode 100644 index 0000000..87e06ae --- /dev/null +++ b/apps/tracker-helper/Dockerfile @@ -0,0 +1,56 @@ +# syntax=docker/dockerfile:1 +FROM debian:stable-slim AS release +ENV PATH=/command:$PATH + +RUN apt-get update -qq \ + && apt-get install -y -qq --no-install-recommends \ + xz-utils \ + unzip \ + ca-certificates \ + curl \ + && export BUN_INSTALL=/home/bun \ + && curl -fsSL https://bun.sh/install | bash -s "bun-v1.2.2" \ + && groupadd bun \ + && useradd bun \ + --gid bun \ + --shell /bin/sh \ + --create-home \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && chown -R bun:bun /home/bun + + +# copy tracker-helper app +COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/node_modules /usr/src/tracker-helper/node_modules +COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/index.ts /usr/src/tracker-helper/ +COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/app.ts /usr/src/tracker-helper/ +COPY --from=gitea.futureporn.net/futureporn/tracker-helper:latest /usr/src/app/package.json /usr/src/tracker-helper/ + +# copy aquatic app +COPY --from=gitea.futureporn.net/futureporn/aquatic:latest /usr/local/bin/aquatic_udp /usr/local/bin/aquatic_udp + +# copy caddy +COPY --from=caddy:alpine /usr/bin/caddy /usr/bin/caddy + +# copy our app (s6-overlay dir structure) +COPY ./root / + + +# 9000/tcp for aquatic_udp metrics /metrics +# and tracker-helper api /helper/* +# Caddy handles the routing for us +EXPOSE 9000/tcp + +# 6969/udp for aquatic_udp +EXPOSE 6969/udp + + +HEALTHCHECK --interval=5s --timeout=3s --retries=3 \ + CMD /etc/tracker/healthcheck.sh + + +ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-noarch.tar.xz /tmp +RUN tar -C / -Jxpf /tmp/s6-overlay-noarch.tar.xz +ADD https://github.com/just-containers/s6-overlay/releases/download/v3.2.0.2/s6-overlay-x86_64.tar.xz /tmp +RUN tar -C / -Jxpf /tmp/s6-overlay-x86_64.tar.xz +ENTRYPOINT ["/init"] \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/aquatic/config.toml b/apps/tracker-helper/root/etc/aquatic/config.toml new file mode 100644 index 0000000..cb5df39 --- /dev/null +++ b/apps/tracker-helper/root/etc/aquatic/config.toml @@ -0,0 +1,27 @@ +log_level = 'debug' + +[network] +use_ipv4 = true +use_ipv6 = true +address_ipv4 = "0.0.0.0:3003" +address_ipv6 = "[::]:3003" + +[statistics] +interval = 5 +print_to_stdout = false +run_prometheus_endpoint = true +prometheus_endpoint_address = "0.0.0.0:9000" + +[access_list] +mode = "allow" +path = "/var/lib/aquatic/accesslist" + +[privileges] +# Chroot and switch group and user after binding to sockets +drop_privileges = true +# Chroot to this path +chroot_path = "/var/lib/aquatic" +# Group to switch to after chrooting +group = "nogroup" +# User to switch to after chrooting +user = "nobody" diff --git a/apps/tracker-helper/root/etc/caddy/Caddyfile b/apps/tracker-helper/root/etc/caddy/Caddyfile new file mode 100644 index 0000000..85c2b6d --- /dev/null +++ b/apps/tracker-helper/root/etc/caddy/Caddyfile @@ -0,0 +1,18 @@ +{ + auto_https off + admin off + http_port 9000 +} + +:9000 { + + # Route for tracker-helper service + handle_path /helper/* { + reverse_proxy localhost:5063 + } + + # Route for Prometheus metrics + handle_path /metrics/* { + reverse_proxy localhost:9000 + } +} \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/run b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/run new file mode 100644 index 0000000..0289c03 --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/run @@ -0,0 +1,3 @@ +#!/command/with-contenv sh + +exec /usr/local/bin/aquatic_udp -c /etc/aquatic/config.toml \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/type b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/type new file mode 100644 index 0000000..1780f9f --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/aquatic/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/dependencies.d/aquatic b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/dependencies.d/aquatic new file mode 100644 index 0000000..e69de29 diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/run b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/run new file mode 100644 index 0000000..e6a0b3d --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/run @@ -0,0 +1,3 @@ +#!/command/with-contenv sh + +/usr/bin/caddy run --config /etc/caddy/Caddyfile \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/type b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/type new file mode 100644 index 0000000..1780f9f --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/caddy/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/dependencies.d/aquatic b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/dependencies.d/aquatic new file mode 100644 index 0000000..e69de29 diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/run b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/run new file mode 100644 index 0000000..55a932d --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/run @@ -0,0 +1,7 @@ +#!/command/with-contenv sh + +export PORT=5063 + +exec 2>&1 +exec s6-setuidgid bun \ + /home/bun/bin/bun run /usr/src/tracker-helper/index.ts \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/type b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/type new file mode 100644 index 0000000..1780f9f --- /dev/null +++ b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/tracker-helper/type @@ -0,0 +1 @@ +longrun \ No newline at end of file diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/aquatic b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/aquatic new file mode 100644 index 0000000..e69de29 diff --git a/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/tracker-helper b/apps/tracker-helper/root/etc/s6-overlay/s6-rc.d/user/contents.d/tracker-helper new file mode 100644 index 0000000..e69de29 diff --git a/apps/tracker-helper/root/etc/tracker/healthcheck.sh b/apps/tracker-helper/root/etc/tracker/healthcheck.sh new file mode 100755 index 0000000..4991d56 --- /dev/null +++ b/apps/tracker-helper/root/etc/tracker/healthcheck.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +pidof aquatic_udp || exit 111 +curl -f http://localhost:5063/helper || exit 112 +curl -f http://localhost:9000/metrics || exit 113 \ No newline at end of file diff --git a/apps/tracker-helper/root/usr/src/tracker-helper/.gitkeep b/apps/tracker-helper/root/usr/src/tracker-helper/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/apps/tracker-helper/root/var/lib/aquatic/accesslist b/apps/tracker-helper/root/var/lib/aquatic/accesslist new file mode 100644 index 0000000..e69de29 diff --git a/config/deploy.yml b/config/deploy.yml index c585e5e..83b2670 100644 --- a/config/deploy.yml +++ b/config/deploy.yml @@ -107,49 +107,24 @@ accessories: - opentracker-etc:/etc/opentracker - opentracker-var:/var/run/opentracker - # opentracker: - # image: gitea.futureporn.net/futureporn/opentracker:latest - # host: 45.76.57.101 - # port: "127.0.0.1:6969:6969" - # env: - # clear: - # WHITELIST_FEED_URL: https://bright.futureporn.net/torrents - # secret: - # - WHITELIST_USERNAME - # - WHITELIST_PASSWORD - # proxy: - # ssl: true - # forward_headers: true - # app_port: 6969 - # host: tracker.futureporn.net - # healthcheck: - # path: /stats - # volumes: - # - opentracker-etc:/etc/opentracker - # - opentracker-var:/var/run/opentracker - - aquatic: - image: gitea.futureporn.net/futureporn/aquatic:latest + tracker: + image: gitea.futureporn.net/futureporn/tracker:latest host: 45.76.57.101 - port: "127.0.0.1:3000:3000" + port: "0.0.0.0:5063:5063" env: clear: - WHITELIST_FEED_URL: https://bright.futureporn.net/torrents + HELPER_ACCESSLIST_PATH: "/var/lib/aquatic/accesslist" secret: - - WHITELIST_USERNAME - - WHITELIST_PASSWORD + - HELPER_USERNAME + - HELPER_PASSWORD + proxy: ssl: true forward_headers: true - app_port: 3000 + app_port: 5063 # note: tracker also uses port 6969/udp and 9000/tcp, but the api at 5063/tcp is what we specify here. # @todo @blocking https://github.com/basecamp/kamal-proxy/issues/48 host: tracker.futureporn.net - ## we can't do the healthcheck on the prometheus port because kamal only allows one port per container - ## @blocking https://github.com/basecamp/kamal-proxy/issues/48 - # healthcheck: - # path: /stats - volumes: - - opentracker-etc:/etc/opentracker - - opentracker-var:/var/run/opentracker + healthcheck: + path: /health qbittorrent: image: lscr.io/linuxserver/qbittorrent:latest diff --git a/docker-compose.yml b/docker-compose.yml index b536795..e230121 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,38 +9,6 @@ services: volumes: - aquatic - # opentracker: - # build: - # context: ./apps/opentracker - # container_name: opentracker - # environment: - # - WHITELIST_FEED_URL=http://bright:4000/torrents - # env_file: - # - .kamal/secrets.development - # ports: - # - "6969:6969/tcp" - # - "6969:6969/udp" - # volumes: - # - opentracker-etc:/etc/opentracker - - # qbittorrent: - # build: - # context: . - # dockerfile: dockerfiles/qbittorrent.dockerfile - # environment: - # - PUID=1000 - # - PGID=1000 - # - UMASK=002 - # - TZ=Etc/UTC - # - WEBUI_PORT=8181 - # - WEBUI_PASSWORD=passwordpassword - # volumes: - # - cache:/root/.cache/futureporn - # container_name: qbittorrent - # ports: - # - "8181:8181/tcp" - - # bright: # container_name: bright diff --git a/services/tracker-helper/test/app.test.ts b/services/tracker-helper/test/app.test.ts deleted file mode 100644 index f2b598e..0000000 --- a/services/tracker-helper/test/app.test.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { - describe - , expect - , it - , beforeEach -} from 'bun:test' -import { - Elysia -} from 'elysia' -import { - treaty -} from '@elysiajs/eden' -import app from '../app.ts' -import Docker from 'dockerode' - - -if (!process.env.WL_FILE_PATH) throw new Error("WL_FILE_PATH is missing in env"); -if (!process.env.WL_USERNAME) throw new Error("WL_USERNAME is missing in env."); -if (!process.env.WL_PASSWORD) throw new Error("WL_PASSWORD is missing in env."); - -const whitelistFilePath = process.env.WL_FILE_PATH! -const fixture = "3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01" - - -const username = process.env.WL_USERNAME! -const password = process.env.WL_PASSWORD! -const opts = { - headers: { - authorization: "Basic " + btoa(username + ':' + password) - } -} -const api = treaty(app) - - - -describe - ('tracker-helper', () => { - - - beforeEach(() => { - let whitelistFilePath = process.env.WL_FILE_PATH! - console.log(`Asserting existance of whitelist at ${whitelistFilePath}`) - // create whitelist file if it doesn't exist - const assertWhitelistExists = async function assertWhitelistExists(whitelistFilePath: string) { - const wlFile = Bun.file(whitelistFilePath); - const exists = await wlFile.exists() - if (!exists) { - console.log(`creating whitelist file at ${whitelistFilePath}`) - await wlFile.write("") - } - } - const clearWhitelist = async function clearWhitelist(whitelistFilePath: string) { - const wlFile = Bun.file(whitelistFilePath); - await wlFile.write("") - } - assertWhitelistExists(whitelistFilePath) - clearWhitelist(whitelistFilePath) - }); - - it('return a health response', async () => { - const { data, status } = await api.health.get() - expect(status).toBe(200) - expect(data).toBe("OK") - }) - - it('return a version', async () => { - const { data, status } = await api.version.get(opts) - expect(status).toBe(200) - expect(data).toContain("version") - }) - - it('return a whitelist', async () => { - const seedWhitelist = async function clearWhitelist(p: string, f: string) { - const wlFile = Bun.file(p); - await wlFile.write(f) - } - await seedWhitelist(whitelistFilePath, fixture) - const { data, status } = await api.whitelist.get(opts) - expect(status).toBe(200) - expect(data).toContain("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01") - }) - - it('expects the whitelist to already exist', async () => { - const whitelist = Bun.file(whitelistFilePath) - const whitelistExists = await whitelist.exists() - expect(whitelistExists).toBe(true) - }) - - it('appends a new info_hash to the whitelist file', async () => { - - - // make an api call which is supposed to add an entry to the whitelist - const { data, status } = await api.whitelist.post(fixture, opts) - - // assert that the entry has been added to the whitelist - - - const w = Bun.file(whitelistFilePath) - const whitelistAfter = await w.text() - console.log('whitelistAfter as follows') - console.log(whitelistAfter) - - expect(status).toBe(201) - expect(data).toMatch(fixture) - expect(whitelistAfter).toMatch(fixture) - - }) - - // it('sends a SIGHUP to opentracker', async () => { - - // const { data, status } = await api.whitelist.post(fixture, opts) - // const containerId = "act-ci-Tests-Checks-6e6f12196682961041a41a25b9d0dcf00e4d0f8e58f-7cb37eebfe9e1670328d58ad1f7c7bdf0fa078298ca6dd299e67d0141a4b9579" - // // await docker.getContainer(containerId).kill({ signal: 'SIGHUP' }) - // let container = await docker.getContainer(containerId) - // container.inspect - - // }) - - - // // This is skipped because I couldn't figure out opentracker's whitelist add/delete via FIFO functionality. - // // I got as far as writing to the FIFO, and seeing opentracker acknowledge the line in it's logs. - // // Despite this, requests from qbittorrent to opentracker responded with, - // // "Requested download is not authorized for use with this tracker" - // // About a week on this problem, and I give up! Using the whitelist reloading strat instead. - // it.skip('writes a new info_hash to a fifo', async () => { - // const fifoFilePath = process.env.WL_FIFO_PATH! - // const fifo = Bun.file(fifoFilePath) - // const fifoExists = await fifo.exists(); - - - // // create fifo if it doesn't exist - // if (!fifoExists) { - // await Bun.spawn(["mkfifo", fifoFilePath]).exited; - // } - - // // Start a process to read from the FIFO - // const reader = Bun.spawn(["cat", fifoFilePath], { stdout: "pipe" }); - - // const { data, status } = await api.whitelist.post("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01", opts) - - // const text = await new Response(reader.stdout).text(); - - // expect(text).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01\n") - // expect(status).toBe(200) - // expect(data).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01") - // }) - - it('returns 401 when username/password is missing from GET /whitelist ', async () => { - const { status } = await api.whitelist.get() - expect(status).toBe(401) - }) - - it('returns 401 when username/password is missing from POST /whitelist ', async () => { - const { status } = await api.whitelist.post() - expect(status).toBe(401) - }) - - }) diff --git a/services/tracker-helper/test/fixtures/taco b/services/tracker-helper/test/fixtures/taco new file mode 100644 index 0000000..0e628b0 --- /dev/null +++ b/services/tracker-helper/test/fixtures/taco @@ -0,0 +1,4 @@ +b22ea43e4c0a7f73fc706b5faf1c35bb078d3722 +3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01 +3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01 +3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01 diff --git a/services/tracker-helper/.dockerignore b/services/tracker/.dockerignore similarity index 100% rename from services/tracker-helper/.dockerignore rename to services/tracker/.dockerignore diff --git a/services/tracker-helper/.gitignore b/services/tracker/.gitignore similarity index 100% rename from services/tracker-helper/.gitignore rename to services/tracker/.gitignore diff --git a/services/tracker-helper/Dockerfile b/services/tracker/Dockerfile similarity index 88% rename from services/tracker-helper/Dockerfile rename to services/tracker/Dockerfile index 45e7af8..aaae4f9 100644 --- a/services/tracker-helper/Dockerfile +++ b/services/tracker/Dockerfile @@ -28,8 +28,8 @@ COPY . . # [optional] tests & build ENV NODE_ENV=test WL_FILE_PATH=/tmp/whitelist -RUN --mount=type=secret,id=WL_USERNAME,env=WL_USERNAME,required=true \ - --mount=type=secret,id=WL_PASSWORD,env=WL_PASSWORD,required=true \ +RUN --mount=type=secret,id=TRACKER_HELPER_USERNAME,env=TRACKER_HELPER_USERNAME,required=true \ + --mount=type=secret,id=TRACKER_HELPER_PASSWORD,env=TRACKER_HELPER_PASSWORD,required=true \ bun test # copy production dependencies and source code into final image diff --git a/services/tracker-helper/README.md b/services/tracker/README.md similarity index 100% rename from services/tracker-helper/README.md rename to services/tracker/README.md diff --git a/services/tracker-helper/app.ts b/services/tracker/app.ts similarity index 74% rename from services/tracker-helper/app.ts rename to services/tracker/app.ts index ed3469a..d9d5a96 100644 --- a/services/tracker-helper/app.ts +++ b/services/tracker/app.ts @@ -4,12 +4,12 @@ import { basicAuth } from '@eelkevdbos/elysia-basic-auth' import net from 'net' import { appendFile } from "node:fs/promises"; -if (!process.env.WL_USERNAME) throw new Error('WL_USERNAME missing in env'); -if (!process.env.WL_PASSWORD) throw new Error('WL_PASSWORD missing in env'); +if (!process.env.TRACKER_HELPER_USERNAME) throw new Error('TRACKER_HELPER_USERNAME missing in env'); +if (!process.env.TRACKER_HELPER_PASSWORD) throw new Error('TRACKER_HELPER_PASSWORD missing in env'); -const whitelistFilePath = process.env.WL_FILE_PATH || "/etc/opentracker/whitelist" -const username = process.env.WL_USERNAME! -const password = process.env.WL_PASSWORD! +const accesslistFilePath = process.env.TRACKER_HELPER_ACCESSLIST_PATH || "/var/lib/aquatic/accesslist" +const username = process.env.TRACKER_HELPER_USERNAME! +const password = process.env.TRACKER_HELPER_PASSWORD! interface DockerContainer { Id: string; @@ -18,7 +18,7 @@ interface DockerContainer { const authOpts = { scope: [ - "/whitelist", + "/accesslist", "/version" ], credentials: [ @@ -32,8 +32,8 @@ const authOpts = { const startupChecks = async function startupChecks() { - if (!process.env.WL_FILE_PATH) { - console.warn(`WL_FILE_PATH is missing in env. Using default ${whitelistFilePath}`) + if (!process.env.TRACKER_HELPER_ACCESSLIST_PATH) { + console.warn(`TRACKER_HELPER_ACCESSLIST_PATH is missing in env. Using default ${accesslistFilePath}`) } } @@ -41,9 +41,9 @@ const startupChecks = async function startupChecks() { -const getWhitelist = async function getWhitelist(ctx: Context) { - const wl = Bun.file(whitelistFilePath); // relative to cwd - console.debug(`read from whitelist file at ${whitelistFilePath}. size=${wl.size}, type=${wl.type}`) +const getAccesslist = async function getAccesslist(ctx: Context) { + const wl = Bun.file(accesslistFilePath); // relative to cwd + console.debug(`read from accesslist file at ${accesslistFilePath}. size=${wl.size}, type=${wl.type}`) return wl.text() } @@ -127,11 +127,11 @@ const maybeKillContainer = async function maybeKillContainer(signal: string = "S } -const postWhitelist = async function postWhitelist(ctx: Context) { +const postAccesslist = async function postAccesslist(ctx: Context) { let body = ctx.body - console.debug('appending to whitelist at ' + whitelistFilePath) - await appendFile(whitelistFilePath, body + "\n"); + console.debug('appending to accesslist at ' + accesslistFilePath) + await appendFile(accesslistFilePath, body + "\n"); await maybeKillContainer("SIGUSR1") @@ -148,8 +148,8 @@ const app = new Elysia() .use(basicAuth(authOpts)) .get('/health', () => 'OK') .get('/version', () => `version ${version}`) - .get('/whitelist', getWhitelist) - .post('/whitelist', postWhitelist, { + .get('/accesslist', getAccesslist) + .post('/accesslist', postAccesslist, { body: t.String() }) diff --git a/services/tracker-helper/bun.lockb b/services/tracker/bun.lockb similarity index 100% rename from services/tracker-helper/bun.lockb rename to services/tracker/bun.lockb diff --git a/services/tracker-helper/fifo-helper.ts b/services/tracker/fifo-helper.ts similarity index 100% rename from services/tracker-helper/fifo-helper.ts rename to services/tracker/fifo-helper.ts diff --git a/services/tracker-helper/index.ts b/services/tracker/index.ts similarity index 100% rename from services/tracker-helper/index.ts rename to services/tracker/index.ts diff --git a/services/tracker-helper/package.json b/services/tracker/package.json similarity index 100% rename from services/tracker-helper/package.json rename to services/tracker/package.json diff --git a/services/tracker-helper/pnpm-lock.yaml b/services/tracker/pnpm-lock.yaml similarity index 100% rename from services/tracker-helper/pnpm-lock.yaml rename to services/tracker/pnpm-lock.yaml diff --git a/services/tracker/test/app.test.ts b/services/tracker/test/app.test.ts new file mode 100644 index 0000000..c169bd6 --- /dev/null +++ b/services/tracker/test/app.test.ts @@ -0,0 +1,156 @@ +import { + describe + , expect + , it + , beforeEach +} from 'bun:test' +import { + Elysia +} from 'elysia' +import { + treaty +} from '@elysiajs/eden' +import app from '../app.ts' +import Docker from 'dockerode' +import { mkdir } from "node:fs/promises"; +import path from 'node:path' + + +if (!process.env.TRACKER_HELPER_USERNAME) throw new Error("TRACKER_HELPER_USERNAME is missing in env."); +if (!process.env.TRACKER_HELPER_PASSWORD) throw new Error("TRACKER_HELPER_PASSWORD is missing in env."); + +const accesslistFilePath = process.env.TRACKER_HELPER_ACCESSLIST_PATH || "/var/lib/aquatic/accesslist" +const fixture = "3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01" // ubuntustudio-22.04.5-dvd-amd64.iso +const fixture2 = "b22ea43e4c0a7f73fc706b5faf1c35bb078d3722" // Solus-GNOME-Release-2025-01-26.iso + +const username = process.env.TRACKER_HELPER_USERNAME! +const password = process.env.TRACKER_HELPER_PASSWORD! +const opts = { + headers: { + authorization: "Basic " + btoa(username + ':' + password) + } +} +const api = treaty(app) + + + +describe + ('tracker-helper', () => { + + + beforeEach(async () => { + console.log(`Asserting existence of accesslist at ${accesslistFilePath}`); + + const assertAccesslistExists = async function (accesslistFilePath: string) { + const wlFile = Bun.file(accesslistFilePath); + const exists = await wlFile.exists(); + + if (!exists) { + console.log(`Creating accesslist file at ${accesslistFilePath}`); + + // Ensure the parent directory exists + await mkdir(path.dirname(accesslistFilePath), { recursive: true }); + + await wlFile.write(`${fixture2}\n${fixture}\n`); + + + } + }; + + await assertAccesslistExists(accesslistFilePath); + }); + + it('return a health response', async () => { + const { data, status } = await api.health.get() + expect(status).toBe(200) + expect(data).toBe("OK") + }) + + it('return a version', async () => { + const { data, status } = await api.version.get(opts) + expect(status).toBe(200) + expect(data).toContain("version") + }) + + it('return a accesslist', async () => { + const { data, status } = await api.accesslist.get(opts) + expect(status).toBe(200) + expect(data).toContain(fixture) + }) + + it('expects the accesslist to already exist', async () => { + const accesslist = Bun.file(accesslistFilePath) + const accesslistExists = await accesslist.exists() + expect(accesslistExists).toBe(true) + }) + + it('appends a new info_hash to the accesslist file', async () => { + + + // make an api call which is supposed to add an entry to the accesslist + const { data, status } = await api.accesslist.post(fixture, opts) + + // assert that the entry has been added to the accesslist + + + const w = Bun.file(accesslistFilePath) + const accesslistAfter = await w.text() + console.log('accesslistAfter as follows') + console.log(accesslistAfter) + + expect(status).toBe(201) + expect(data).toMatch(fixture) + expect(accesslistAfter).toMatch(fixture) + + }) + + // it('sends a SIGHUP to opentracker', async () => { + + // const { data, status } = await api.accesslist.post(fixture, opts) + // const containerId = "act-ci-Tests-Checks-6e6f12196682961041a41a25b9d0dcf00e4d0f8e58f-7cb37eebfe9e1670328d58ad1f7c7bdf0fa078298ca6dd299e67d0141a4b9579" + // // await docker.getContainer(containerId).kill({ signal: 'SIGHUP' }) + // let container = await docker.getContainer(containerId) + // container.inspect + + // }) + + + // // This is skipped because I couldn't figure out opentracker's accesslist add/delete via FIFO functionality. + // // I got as far as writing to the FIFO, and seeing opentracker acknowledge the line in it's logs. + // // Despite this, requests from qbittorrent to opentracker responded with, + // // "Requested download is not authorized for use with this tracker" + // // About a week on this problem, and I give up! Using the accesslist reloading strat instead. + // it.skip('writes a new info_hash to a fifo', async () => { + // const fifoFilePath = process.env.TRACKER_HELPER_FIFO_PATH! + // const fifo = Bun.file(fifoFilePath) + // const fifoExists = await fifo.exists(); + + + // // create fifo if it doesn't exist + // if (!fifoExists) { + // await Bun.spawn(["mkfifo", fifoFilePath]).exited; + // } + + // // Start a process to read from the FIFO + // const reader = Bun.spawn(["cat", fifoFilePath], { stdout: "pipe" }); + + // const { data, status } = await api.accesslist.post("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01", opts) + + // const text = await new Response(reader.stdout).text(); + + // expect(text).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01\n") + // expect(status).toBe(200) + // expect(data).toBe("3aa5ad5e62eaffd148cff3dbe93ff2e1e9cbcf01") + // }) + + it('returns 401 when username/password is missing from GET /accesslist ', async () => { + const { status } = await api.accesslist.get() + expect(status).toBe(401) + }) + + it('returns 401 when username/password is missing from POST /accesslist ', async () => { + const { status } = await api.accesslist.post() + expect(status).toBe(401) + }) + + }) diff --git a/services/tracker-helper/test/fixtures/whitelist b/services/tracker/test/fixtures/whitelist similarity index 100% rename from services/tracker-helper/test/fixtures/whitelist rename to services/tracker/test/fixtures/whitelist diff --git a/services/tracker-helper/tsconfig.json b/services/tracker/tsconfig.json similarity index 100% rename from services/tracker-helper/tsconfig.json rename to services/tracker/tsconfig.json