diff --git a/.ci/build_release.sh b/.ci/build_release.sh deleted file mode 100755 index a17402632..000000000 --- a/.ci/build_release.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -set -e - -od=$(pwd) -mix local.hex --force && mix local.rebar --force -mix do deps.get, deps.compile -cd apps/cf_http/assets && npm ci --progress=false --no-audit --loglevel=error -cd $od -npm run --prefix apps/cf_http/assets deploy -cd apps/cf_http -mix phx.digest -cd $od -mix release --overwrite --force diff --git a/.ci/build_ubuntu_18.04.sh b/.ci/build_ubuntu_18.04.sh new file mode 100755 index 000000000..519992384 --- /dev/null +++ b/.ci/build_ubuntu_18.04.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e + +OS="ubuntu_18.04" +ARCH=${MATRIX_ARCH:-`uname -m`} +PKG_DIR="${OS}_${ARCH}" +PKG_FILE="${PKG_DIR}.deb" +IMAGE="${OS}_${ARCH}:latest" + +docker build \ + -t $IMAGE \ + -f pkg/Dockerfile.$OS \ + --platform linux/$ARCH \ + --build-arg PKG_DIR=$PKG_DIR \ + --progress plain \ + . + +CID=$(docker create $IMAGE) +mkdir -p _build +docker cp $CID:/build/pkg/$PKG_FILE ./_build/cloudfire_$PKG_FILE diff --git a/.ci/build_ubuntu_20.04.sh b/.ci/build_ubuntu_20.04.sh new file mode 100755 index 000000000..e702ea62b --- /dev/null +++ b/.ci/build_ubuntu_20.04.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -e + +OS="ubuntu_20.04" +ARCH=${MATRIX_ARCH:-`uname -m`} +PKG_DIR="${OS}_${ARCH}" +PKG_FILE="${PKG_DIR}.deb" +IMAGE="${OS}_${ARCH}:latest" + +docker build \ + -t $IMAGE \ + -f pkg/Dockerfile.$OS \ + --platform linux/$ARCH \ + --build-arg PKG_DIR=$PKG_DIR \ + --progress plain \ + . + +CID=$(docker create $IMAGE) +mkdir -p _build +docker cp $CID:/build/pkg/$PKG_FILE ./_build/cloudfire_$PKG_FILE diff --git a/.ci/functional_test.sh b/.ci/functional_test.sh index 2f3263de6..5039d4c4e 100755 --- a/.ci/functional_test.sh +++ b/.ci/functional_test.sh @@ -1,27 +1,24 @@ #!/usr/bin/env bash -set -e +set -x -chmod +x cloudfire +sudo apt-get update +sudo apt-get install -y -q postgresql \ + wireguard iptables net-tools curl ca-certificates +sudo systemctl start postgresql +sudo dpkg -i *.deb -# Needed because binaries built with Bakeware assume directory exists -mkdir $HOME/.cache - -echo "Initializing default config..." -curl https://raw.githubusercontent.com/CloudFire-LLC/cloudfire/${GITHUB_SHA}/scripts/init_config.sh | bash - - -# Create DB -export PGPASSWORD=postgres # used by psql -sudo -E -u postgres psql -d postgres -h localhost -c "CREATE DATABASE cloudfire;" - -# Start by running migrations always -./cloudfire eval "CfHttp.Release.migrate" - -# Start in the background -./cloudfire & +echo "Enabling service..." +sudo systemctl start cloudfire # Wait for app to start sleep 10 +echo "Service status..." +sudo systemctl status cloudfire.service + +echo "Printing service logs..." +sudo journalctl -u cloudfire.service + echo "Trying to load homepage..." curl -i -vvv -k https://$(hostname):8800/ diff --git a/.ci/install_runtimes.sh b/.ci/install_runtimes.sh index b23e72732..7f9a24abb 100755 --- a/.ci/install_runtimes.sh +++ b/.ci/install_runtimes.sh @@ -3,9 +3,9 @@ set -e os_name='ubuntu~bionic' -curl -O https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_24.0.2-1~${os_name}_${arch}.deb +curl -O https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_24.0.2-1~${os_name}_${MATRIX_ARCH}.deb curl -O https://packages.erlang-solutions.com/erlang/debian/pool/elixir_1.12.0-1~${os_name}_all.deb gdebi --non-interactive *.deb curl -sL https://deb.nodesource.com/setup_14.x | bash - -apt-get install -y -q gcc g++ make nodejs cargo +apt-get install -y -q gcc g++ make nodejs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ca039bf1..ab549e2a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,18 @@ jobs: POSTGRES_HOST: localhost GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} MATRIX_OS: ubuntu-18.04 - arch: amd64 + MATRIX_ARCH: amd64 + strategy: + matrix: + postgres: + - postgres:9.6 + - postgres:10 + - postgres:11 + - postgres:12 + - postgres:13 services: postgres: - image: postgres:13 + image: ${{ matrix.postgres }} ports: - 5432:5432 env: @@ -56,123 +64,144 @@ jobs: name: test screenshots path: apps/cf_http/screenshots - build-linux: + build: needs: unit-integration-test - runs-on: ubuntu-18.04 - name: Build on {{ matrix.arch }} + runs-on: ubuntu-20.04 + name: Build env: - arch: ${{ matrix.arch }} + MATRIX_ARCH: ${{ matrix.arch }} + MATRIX_OS: ${{ matrix.os }} MIX_ENV: prod strategy: matrix: + os: + # - amazonlinux_2 + # - debian_10 + - ubuntu_18.04 + - ubuntu_20.04 + # - redhat_7 + # - redhat_8 + # - centos_7 + # - centos_8 include: - arch: amd64 - - arch: arm64 + # XXX: This currently takes upwards of 10 minutes or more. Disabling for now + # - arch: arm64 steps: - uses: actions/checkout@v2 + - uses: satackey/action-docker-layer-caching@v0.0.11 + continue-on-error: false + with: + key: docker-cache-${{ matrix.os }}-${{ matrix.arch }}-${{ github.sha }} + restore-keys: | + docker-cache-${{ matrix.os }}-${{ matrix.arch }}- # amd64 build - if: ${{ matrix.arch == 'amd64' }} - run: | - sudo apt-get install -q -y zstd gdebi - sudo -E bash -c '.ci/install_runtimes.sh' - sudo -E bash -c '.ci/build_release.sh' + run: .ci/build_${{ matrix.os }}.sh # arm64 build - # XXX: This currently takes upwards of 10 minutes or more. Disabling for - # now. - # - uses: uraimo/run-on-arch-action@v2.0.10 - # if: ${{ matrix.arch == 'arm64' }} - # name: Run on arm64 - # with: - # arch: aarch64 - # install: | - # # No obvious way to load a script file here, so needs inlining :-( - # apt-get update -q -y - # apt-get install -q -y gcc g++ make curl gdebi zstd - # - # curl -O https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_24.0.2-1~ubuntu~bionic_arm64.deb - # curl -O https://packages.erlang-solutions.com/erlang/debian/pool/elixir_1.12.0-1~ubuntu~bionic_all.deb - # gdebi --non-interactive esl-erlang_24.0.2-1~ubuntu~bionic_arm64.deb - # gdebi --non-interactive elixir_1.12.0-1~ubuntu~bionic_all.deb - # - # curl -sL https://deb.nodesource.com/setup_14.x | bash - - # apt-get install -y -q nodejs - # dockerRunArgs: | - # --volume "${PWD}:/app" - # distro: ubuntu18.04 - # env: | - # arch: arm64 - # githubToken: ${{ github.token }} - # run: | - # cd /app - # bash -c '.ci/build_release.sh' + - uses: uraimo/run-on-arch-action@v2.0.10 + if: ${{ matrix.arch == 'arm64' }} + with: + arch: aarch64 + install: | + # No obvious way to load a script file here, so needs inlining :-( + apt-get update -q -y + apt-get install -q -y gcc g++ make curl gdebi zstd + + curl -O https://packages.erlang-solutions.com/erlang/debian/pool/esl-erlang_24.0.2-1~ubuntu~bionic_arm64.deb + curl -O https://packages.erlang-solutions.com/erlang/debian/pool/elixir_1.12.0-1~ubuntu~bionic_all.deb + gdebi --non-interactive esl-erlang_24.0.2-1~ubuntu~bionic_arm64.deb + gdebi --non-interactive elixir_1.12.0-1~ubuntu~bionic_all.deb + + curl -sL https://deb.nodesource.com/setup_14.x | bash - + apt-get install -y -q nodejs + dockerRunArgs: | + --volume "${PWD}:/app" + distro: ubuntu18.04 + env: | + arch: arm64 + githubToken: ${{ github.token }} + run: | + cd /app + bash -c '.ci/build_release.sh' - uses: actions/upload-artifact@v2 with: - name: cloudfire-${{ matrix.arch }} - path: _build/prod/rel/bakeware/cloudfire + name: cloudfire_${{ matrix.os }}_${{ matrix.arch }}.deb + path: _build/cloudfire_${{ matrix.os }}_${{ matrix.arch }}.deb functional-test: - needs: build-linux - runs-on: ${{ matrix.os }} + needs: build + runs-on: ubuntu-20.04 strategy: matrix: - os: [ubuntu-18.04] + os: + # - amazonlinux_2 + # - debian_10 + - ubuntu_18.04 + - ubuntu_20.04 + # - redhat_7 + # - redhat_8 + # - centos_7 + # - centos_8 + include: + - arch: amd64 + # - arch: arm64 env: MATRIX_OS: ${{ matrix.os }} - services: - postgres: - image: postgres:13 - ports: - - 5432:5432 - env: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 + MATRIX_ARCH: ${{ matrix.arch }} + DEBIAN_FRONTEND: noninteractive steps: - uses: actions/checkout@v2 - uses: actions/download-artifact@v2 with: - name: cloudfire-amd64 - - run: sudo apt-get install -q -y wireguard + name: cloudfire_${{ matrix.os }}_${{ matrix.arch }}.deb + path: ./ - name: Test Install package - env: - DEBIAN_FRONTEND: noninteractive run: .ci/functional_test.sh - # - # publish: - # needs: functional-test - # runs-on: ${{ matrix.os }} - # strategy: - # matrix: - # os: [ubuntu-20.04] - # if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') - # steps: - # - name: Create Release - # id: create_release - # uses: actions/create-release@v1 - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # with: - # tag_name: ${{ github.ref }} - # release_name: Release ${{ github.ref }} - # draft: false - # prerelease: true - # - uses: actions/download-artifact@v2 - # with: - # name: cloudfire-deb - # - name: Upload Release Asset - # id: upload-release-asset - # uses: actions/upload-release-asset@v1 - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # with: - # upload_url: ${{ steps.create_release.outputs.upload_url }} - # asset_path: ./cloudfire_${{ github.sha }}-1_${{ matrix.os }}_amd64.deb - # asset_name: cloudfire_${{ matrix.os }}_amd64.deb - # asset_content_type: application/vnd.debian.binary-package + + publish: + needs: functional-test + runs-on: ubuntu-20.04 + strategy: + matrix: + os: + # - amazonlinux_2 + # - debian_10 + - ubuntu_18.04 + - ubuntu_20.04 + # - redhat_7 + # - redhat_8 + # - centos_7 + # - centos_8 + include: + - arch: amd64 + # - arch: arm64 + if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') + steps: + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: Release ${{ github.ref }} + draft: false + prerelease: true + - uses: actions/download-artifact@v2 + with: + name: cloudfire_${{ matrix.os }}_${{ matrix.arch }} + path: ./ + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./cloudfire_${{ matrix.os }}_${{ matrix.arch }}.deb + asset_name: ${{ matrix.os }}_${{ matrix.arch }} + asset_content_type: application/vnd.debian.binary-package diff --git a/.tool-versions b/.tool-versions index 7d8c873e8..709b34441 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,4 +1,3 @@ erlang 24.0.3 -elixir 1.12.1-otp-24 +elixir 1.12.2-otp-24 nodejs lts -rust system diff --git a/README.md b/README.md index 4d8533dc5..1576cde42 100644 --- a/README.md +++ b/README.md @@ -45,22 +45,18 @@ For now, `cloudfire` assumes these apps are all running on the same host. Prerequisites: 1. Postgresql Server 9.6 or higher. Access can be configured in - `~/.cloudfire/config.json` after installation. + `/opt/cloudfire/config.env` after installation. 2. `wg`, `openssl`, `ip`, and `iptables` must be in your PATH. -Then you can install `cloudfire` with: - -`curl https://raw.githubusercontent.com/CloudFire-LLC/cloudfire/master/scripts/install.sh | bash -` - -This will download the `cloudfire` binary, initialize the config directory, and -print further instructions to the console. +Then you can install `cloudfire` by [downloading the appropriate package +from the releases page](https://github.com/CloudFire-LLC/cloudfire/releases). ## Creating additional admin users You may create additional admin users with the following command: ```bash -cloudfire rpc 'CfHttp.Users.create_user( +/opt/cloudfire/bin/cloudfire rpc 'CfHttp.Users.create_user( email: "USER_EMAIL", password: "USER_PASSWORD", password_confirmation: "USER_PASSWORD" diff --git a/apps/cf_common/lib/config_file.ex b/apps/cf_common/lib/config_file.ex deleted file mode 100644 index 0657a4539..000000000 --- a/apps/cf_common/lib/config_file.ex +++ /dev/null @@ -1,26 +0,0 @@ -defmodule CfCommon.ConfigFile do - @moduledoc """ - Common config file operations. - """ - - def load! do - %{} = Jason.decode!(file_module().read!(config_path())) - end - - def write!(config) do - config_path() - |> file_module().write!(Jason.encode!(config), [:write]) - end - - def exists? do - file_module().exists?(config_path()) - end - - defp config_path do - System.fetch_env!("HOME") <> "/.cloudfire/config.json" - end - - defp file_module do - Application.fetch_env!(:cf_common, :config_file_module) - end -end diff --git a/apps/cf_common/lib/fake_file.ex b/apps/cf_common/lib/fake_file.ex deleted file mode 100644 index 3ec88d4bc..000000000 --- a/apps/cf_common/lib/fake_file.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule CfCommon.FakeFile do - @moduledoc """ - Provides mocked file operations for testing ConfigFile - """ - - @json ~s({ - "database_url": "ecto://postgres:postgres@127.0.0.1/cloudfire", - "secret_key_base": "fMjyDw9RpP5+f8klEmeEWnBQKd2H7uKH/PQpOTug6vybretclzaE1k4Y3O2Bw8lX", - "live_view_signing_salt": "EHcSipS+bFTFYMbFmvVR8lAuwYyfqcTE", - "db_encryption_key": "8Wgh3dPubt6q4Y1PlYRuG9v50zQE+QTUzh8mJnkw+jc=", - "ssl_cert_file": "$HOME/.cloudfire/ssl/cert.pem", - "ssl_key_file": "$HOME/.cloudfire/ssl/key.pem", - "url_host": "localhost", - "wg_server_key": "KDp9lQ6OAi/VrfgYo5VIAqCJFs1Gs55GZRDoA7W8500=", - "https_listen_port": "8800", - "https_listen_address": "127.0.0.1", - "wg_listen_port": "51820" - }) - - def read!(_), do: @json - def write!(_, _, [:write]), do: :ok - def exists?(_), do: true -end diff --git a/apps/cf_common/test/config_file_test.exs b/apps/cf_common/test/config_file_test.exs deleted file mode 100644 index f973a0c27..000000000 --- a/apps/cf_common/test/config_file_test.exs +++ /dev/null @@ -1,37 +0,0 @@ -defmodule CfCommon.ConfigFileTest do - use ExUnit.Case, async: true - - alias CfCommon.ConfigFile - - @expected_config %{ - "database_url" => "ecto://postgres:postgres@127.0.0.1/cloudfire", - "secret_key_base" => "fMjyDw9RpP5+f8klEmeEWnBQKd2H7uKH/PQpOTug6vybretclzaE1k4Y3O2Bw8lX", - "live_view_signing_salt" => "EHcSipS+bFTFYMbFmvVR8lAuwYyfqcTE", - "db_encryption_key" => "8Wgh3dPubt6q4Y1PlYRuG9v50zQE+QTUzh8mJnkw+jc=", - "ssl_cert_file" => "$HOME/.cloudfire/ssl/cert.pem", - "ssl_key_file" => "$HOME/.cloudfire/ssl/key.pem", - "url_host" => "localhost", - "wg_server_key" => "KDp9lQ6OAi/VrfgYo5VIAqCJFs1Gs55GZRDoA7W8500=", - "https_listen_port" => "8800", - "https_listen_address" => "127.0.0.1", - "wg_listen_port" => "51820" - } - - describe "load!" do - test "loads stubbed config" do - assert ConfigFile.load!() == @expected_config - end - end - - describe "write!" do - test "returns :ok" do - assert ConfigFile.write!(@expected_config) == :ok - end - end - - describe "exists?" do - test "returns true" do - assert ConfigFile.exists?() - end - end -end diff --git a/apps/cf_http/assets/static/logo.svg b/apps/cf_http/assets/static/logo.svg index bc06cd0ed..24d14fafc 100644 --- a/apps/cf_http/assets/static/logo.svg +++ b/apps/cf_http/assets/static/logo.svg @@ -1,13 +1,13 @@ - + - Slice + Group Created with Sketch. - - CloudFire + + FireZone