Add zero-config self hosting on Render #612

Merged
zachgoll merged 42 commits from self-hosting into main 2024-04-13 21:28:45 +08:00
zachgoll commented 2024-04-11 07:14:41 +08:00 (Migrated from github.com)

This PR introduces a system to allow for "zero config" / "one-click" self hosting deploys.

Overview

Below are some highlights of what this solution aims to accomplish:

  • A user can deploy to the Render hosting platform in one click, for free, in less than 5 minutes
    • Additional configuration will be done in the UI by the user to enhance the app experience.
  • A user can choose their updates mode and configure it in the UI:
    • disabled - this turns off auto-updates. The user will be prompted in the UI for each new release and can manually upgrade if they wish
    • release - this automatically upgrades the self-hosted app each time a new release becomes available. This is the "stable" option
    • commit - this automatically upgrades the self-hosted app to the latest commit and mirrors Render's "auto deploy" functionality
  • Each time the app is upgraded, the user will see a release alert exactly one time with notes of what changed

Technical Features

The main goal with this system design is to enable a self-hoster to get their app running without touching any code and enable incremental configuration via the UI.

  • The Upgrader class/namespace has been designed to be agnostic of the hosting platform. To support a new platform (such as Docker, Heroku, etc.), all that needs to be added is some configuration and a Upgrader::Deployer::<Platform> class that knows how to auto-deploy the self hosted app
  • The Upgrader is provided with git repository data using the pattern introduced in #561 to keep track of new commits and releases that are available for upgrade
  • config/initializers/version.rb stores a hardcoded version number which will be updated manually each new release. This is required so the app knows which commits and releases are available for upgrade.
  • The rails-settings-cached gem is used for global settings and can be 100% configured via environment variables and later changed in the UI by the self-hosting user.
    • For example, when deploying to Render, the user will need to supply the app with a deploy hook to trigger upgrades. Since this is not available until after the service is deployed, I have made this one of the dynamic settings that the user will be prompted to enter in the UI

Upgrades

As described above—all users (whether self-hosted or paying users) will see notifications of new releases with changelogs. Self-hosted users will see special "prompts" to upgrade and can trigger new deploys within their app.

https://github.com/maybe-finance/maybe/assets/16676157/fb7c1786-f521-4227-80ee-0b5be38efbbe

Docker

This solution provides an extension point for setting up a Docker compose self-hosting configuration. In the future, a self-hosting user should be able to deploy to any Linux-enabled VPS with a single command (not supported yet):

# Not implemented yet
curl -fsSL https://raw.githubusercontent.com/maybe-finance/maybe/main/install.sh | bash
This PR introduces a system to allow for "zero config" / "one-click" self hosting deploys. ## Overview Below are some highlights of what this solution aims to accomplish: - A user can deploy to the [Render hosting platform](https://render.com/) in one click, for free, in less than 5 minutes - Additional configuration will be done in the UI by the user to enhance the app experience. - A user can choose their updates mode and configure it in the UI: - `disabled` - this turns off auto-updates. The user will be prompted in the UI for each new release and can manually upgrade if they wish - `release` - this automatically upgrades the self-hosted app each time a new release becomes available. This is the "stable" option - `commit` - this automatically upgrades the self-hosted app to the latest commit and mirrors Render's "auto deploy" functionality - Each time the app is upgraded, the user will see a release alert exactly one time with notes of what changed ### Technical Features The main goal with this system design is to enable a self-hoster to get their app running without touching any code and enable _incremental configuration_ via the UI. - The `Upgrader` class/namespace has been designed to be _agnostic_ of the hosting platform. To support a new platform (such as Docker, Heroku, etc.), all that needs to be added is some configuration and a `Upgrader::Deployer::<Platform>` class that knows how to auto-deploy the self hosted app - The `Upgrader` is provided with git repository data using the pattern introduced in #561 to keep track of new commits and releases that are available for upgrade - `config/initializers/version.rb` stores a hardcoded version number which will be updated manually each new release. This is required so the app knows which commits and releases are available for upgrade. - The `rails-settings-cached` gem is used for global settings and can be 100% configured via environment variables and later changed in the UI by the self-hosting user. - For example, when deploying to Render, the user will need to supply the app with a [deploy hook](https://docs.render.com/deploy-hooks) to trigger upgrades. Since this is not available until _after_ the service is deployed, I have made this one of the dynamic settings that the user will be prompted to enter in the UI ### Upgrades As described above—all users (whether self-hosted or paying users) will see notifications of new releases with changelogs. Self-hosted users will see special "prompts" to upgrade and can trigger new deploys within their app. https://github.com/maybe-finance/maybe/assets/16676157/fb7c1786-f521-4227-80ee-0b5be38efbbe ### Docker This solution provides an extension point for setting up a Docker compose self-hosting configuration. In the future, a self-hosting user should be able to deploy to _any_ Linux-enabled VPS with a single command (not supported yet): ```sh # Not implemented yet curl -fsSL https://raw.githubusercontent.com/maybe-finance/maybe/main/install.sh | bash ```
pieterbeulque (Migrated from github.com) reviewed 2024-04-11 16:22:30 +08:00
@@ -2,6 +2,24 @@
# exit on error
pieterbeulque (Migrated from github.com) commented 2024-04-11 16:22:30 +08:00
echo "Precompiling assets..."
```suggestion echo "Precompiling assets..." ```
johnbeynon (Migrated from github.com) reviewed 2024-04-12 04:22:45 +08:00
@@ -0,0 +1,57 @@
databases:
johnbeynon (Migrated from github.com) commented 2024-04-12 04:22:45 +08:00

I'd suggest moving the db:migrate into the build script - you probably don't want the DB migrate task running for every start of the service

I'd suggest moving the db:migrate into the build script - you probably don't want the DB migrate task running for every start of the service
zachgoll (Migrated from github.com) reviewed 2024-04-12 05:30:02 +08:00
@@ -0,0 +1,57 @@
databases:
zachgoll (Migrated from github.com) commented 2024-04-12 05:30:02 +08:00

That's true, I'll go ahead and make that change.

Ideally this is run in preDeployCommand, so I may add something like this to the render-build.sh script:

# Self-hosting users who upgrade their service should remove the environment variable RUN_DB_MIGRATIONS_IN_BUILD_STEP
# since the database will be migrated in the `preDeployCommand` (a premium Render feature)
if [ "$RUN_DB_MIGRATIONS_IN_BUILD_STEP" = "true" ]; then
  echo "Running migrations for free tier instance..."
  bundle exec rails db:migrate
fi

That's true, I'll go ahead and make that change. Ideally this is run in `preDeployCommand`, so I may add something like this to the `render-build.sh` script: ```sh # Self-hosting users who upgrade their service should remove the environment variable RUN_DB_MIGRATIONS_IN_BUILD_STEP # since the database will be migrated in the `preDeployCommand` (a premium Render feature) if [ "$RUN_DB_MIGRATIONS_IN_BUILD_STEP" = "true" ]; then echo "Running migrations for free tier instance..." bundle exec rails db:migrate fi ```
Sign in to join this conversation.