-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tutorial for setting up AppFlowy on Hetzner Cloud #959
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,255 @@ | ||||||
--- | ||||||
SPDX-License-Identifier: MIT | ||||||
path: "/tutorials/install-and-configure-appflowy-with-hetzner-object-storage" | ||||||
slug: "install-and-configure-appflowy-with-hetzner-object-storage" | ||||||
date: "2024-10-01" | ||||||
title: "Install and configure AppFlowy with Hetzner Object Storage" | ||||||
short_description: "A guide on how to setup your own AppFlowy Cloud Server using Hetzner Object Storage and Hetzner Cloud Server." | ||||||
tags: ["AppFlowy", "Object Storage", "Cloud"] | ||||||
author: "Stefan Weiberg" | ||||||
author_link: "https://github.com/suntorytimed" | ||||||
author_img: "https://avatars.githubusercontent.com/u/2744377" | ||||||
author_description: "" | ||||||
language: "en" | ||||||
available_languages: ["en"] | ||||||
header_img: "header-4" | ||||||
cta: "objectstorage" | ||||||
--- | ||||||
|
||||||
## Introduction | ||||||
|
||||||
In this tutorial we are going to setup our own AppFlowy Cloud server using the official documentation by AppFlowy. We will use a Hetzner Cloud Server and the new Hetzner Object Storage. This tutorial won't cover how you create a new project called "AppFlowy", and how Hetzner Cloud servers are created. We will purely focus on setting up AppFlowy, setting up a bucket and connecting it to our AppFlowy Cloud server. | ||||||
|
||||||
### Prerequisites | ||||||
|
||||||
* Hetzner Cloud server with git, docker and docker-compose installed and access via SSH or web terminal in the Hetzner Cloud console | ||||||
* DNS entry for your desired (sub-)domain to your Hetzner Cloud server | ||||||
* Optional: Dedicated Hetzner Cloud project called "AppFlowy" to pool you resources together | ||||||
|
||||||
## Step 1 - Create a bucket | ||||||
|
||||||
First, we will create a new bucket in the Hetzner Cloud console. | ||||||
|
||||||
![Click on "Create Bucket" in your project](images/create_bucket.png) | ||||||
|
||||||
As the name of the bucket we chooose appflowy and add a UUID after it to make it unique. We can create the bucket with private visibility, as the access will happen via the Hetzner Cloud server. | ||||||
|
||||||
![Choose a unique bucket name and click on "Create & Buy now"](images/name_bucket.png) | ||||||
|
||||||
After successfully creating the bucket, open it and copy the URL of the bucket, by clicking on it. Paste the URL into a file for later. Click on "Manage credentials" on the same screen to access the page for S3 credential creation. | ||||||
|
||||||
![Copy the URL of your bucket](images/bucket_url.png) | ||||||
|
||||||
Click on "Generate credentials" to create new credentials for your AppFlowy Cloud server. | ||||||
|
||||||
![Click on "Generate credentials"](images/generate_credentials.png) | ||||||
|
||||||
Choose a description for your new credentials. | ||||||
|
||||||
![Click on "Generate credentials"](images/description_credentials.png) | ||||||
|
||||||
Copy and store your access key and secret key for later usage. | ||||||
|
||||||
![Copy your keys](images/key_credentials.png) | ||||||
|
||||||
## Step 2 - Setup your AppFlowy Cloud server | ||||||
|
||||||
SSH into your server or use the Hetzner Cloud Console terminal to access your server via the web frontend. | ||||||
|
||||||
### Step 2.1 - Clone the AppFlowy Cloud repository | ||||||
|
||||||
Clone the AppFlowy-Cloud repository to your desired location and `cd` into the cloned repository: | ||||||
|
||||||
``` | ||||||
git clone https://github.com/AppFlowy-IO/AppFlowy-Cloud | ||||||
cd AppFlowy-Cloud | ||||||
``` | ||||||
|
||||||
### Step 2.2 - Setup the nginx proxy of AppFlowy Cloud to use your SSL certificate | ||||||
|
||||||
Put your SSL certificate and private key in the folder ./nginx/ssl/ or adjust the location in the docker-compose.yml to point to your own certificates. Alternatively you can create a Let's Encrypt SSL certificate via DNS challenge on the Hetzner DNS service by using lego: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
go install github.com/go-acme/lego/v4/cmd/lego@latest | ||||||
~/go/bin/lego --domains="appflowy.example.com" --email="[email protected]" --http run | ||||||
``` | ||||||
|
||||||
And adjust the docker-compose.yml to point to the output folder of lego: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
nginx: | ||||||
restart: on-failure | ||||||
image: nginx | ||||||
ports: | ||||||
- ${NGINX_PORT:-80}:80 # Disable this if you are using TLS | ||||||
- ${NGINX_TLS_PORT:-443}:443 | ||||||
volumes: | ||||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf | ||||||
- ./.lego/certificates/appflowy.example.com.crt:/etc/nginx/ssl/certificate.crt | ||||||
- ./.lego/certificates/appflowy.example.com.key:/etc/nginx/ssl/private_key.key | ||||||
``` | ||||||
|
||||||
### Step 2.3 - Remove the minio service from the docker-compose.yml | ||||||
|
||||||
Remove the minio service from the docker-compose.yml by deleting following lines: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
# You do not need this if you have configured to use your own s3 file storage | ||||||
minio: | ||||||
restart: on-failure | ||||||
image: minio/minio | ||||||
environment: | ||||||
- MINIO_BROWSER_REDIRECT_URL=http://localhost/minio | ||||||
- MINIO_ROOT_USER=${APPFLOWY_S3_ACCESS_KEY:-minioadmin} | ||||||
- MINIO_ROOT_PASSWORD=${APPFLOWY_S3_SECRET_KEY:-minioadmin} | ||||||
command: server /data --console-address ":9001" | ||||||
volumes: | ||||||
- minio_data:/data | ||||||
``` | ||||||
|
||||||
Don't forget to remove the minio_data volume from the volumes at the end of the docker-compose.yml. Only the postgres_data volume should remain: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
volumes: | ||||||
postgres_data: | ||||||
``` | ||||||
|
||||||
### Step 2.4 - Adjust the deploy.env | ||||||
|
||||||
Now we need to adjust the deploy.env file to use our own passwords and point to the Hetzner Object Storage. I recommend to keep the order of values identical, as we are going to commit our changes locally. This makes rebasing easier. At the time of creation of this tutorial you should adjust following values with your own password and SMTP configuration: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
# change password and secret | ||||||
# change your database name if needed | ||||||
APPFLOWY_DATABASE_URL=postgres://postgres:password@postgres:5432/postgres | ||||||
GOTRUE_JWT_SECRET=hello456 | ||||||
GOTRUE_DATABASE_URL=postgres://supabase_auth_admin:root@postgres:5432/postgres | ||||||
APPFLOWY_AI_DATABASE_URL=postgresql+psycopg://postgres:password@postgres:5432/postgres | ||||||
APPFLOWY_HISTORY_DATABASE_URL=postgres://postgres:password@postgres:5432/postgres | ||||||
APPFLOWY_INDEXER_DATABASE_URL=postgres://postgres:password@postgres:5432/postgres | ||||||
|
||||||
# replace with your own SMTP configuration | ||||||
GOTRUE_SMTP_HOST=smtp.gmail.com | ||||||
GOTRUE_SMTP_PORT=465 | ||||||
GOTRUE_SMTP_USER=email_sender@some_company.com | ||||||
GOTRUE_SMTP_PASS=email_sender_password | ||||||
GOTRUE_SMTP_ADMIN_EMAIL=comp_admin@some_company.com | ||||||
APPFLOWY_MAILER_SMTP_HOST=smtp.gmail.com | ||||||
APPFLOWY_MAILER_SMTP_PORT=465 | ||||||
APPFLOWY_MAILER_SMTP_USERNAME=email_sender@some_company.com | ||||||
APPFLOWY_MAILER_SMTP_PASSWORD=email_sender_password | ||||||
|
||||||
# configure your admin account | ||||||
[email protected] | ||||||
GOTRUE_ADMIN_PASSWORD=password | ||||||
|
||||||
# input your (sub-)domain, which you configured in the Hetzner DNS service | ||||||
API_EXTERNAL_URL=http://your-host | ||||||
|
||||||
``` | ||||||
|
||||||
Remove following lines from the deploy.env, as we won't use those services: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
# PgAdmin | ||||||
# Optional module to manage the postgres database | ||||||
# You can access the pgadmin at http://your-host/pgadmin | ||||||
# Refer to the APPFLOWY_DATABASE_URL for password when connecting to the database | ||||||
[email protected] | ||||||
PGADMIN_DEFAULT_PASSWORD=password | ||||||
|
||||||
# Portainer (username: admin) | ||||||
PORTAINER_PASSWORD=password1234 | ||||||
|
||||||
# Cloudflare tunnel token | ||||||
CLOUDFLARE_TUNNEL_TOKEN= | ||||||
``` | ||||||
|
||||||
And finally configure your Object Storage: | ||||||
|
||||||
``` | ||||||
APPFLOWY_S3_USE_MINIO=true | ||||||
APPFLOWY_S3_MINIO_URL=https://appflowy-5d3f1744a2494fb5b49c983e3eff3e17.fsn1.your-objectstorage.com # this is where the previously copied Object Storage URL is pasted | ||||||
APPFLOWY_S3_ACCESS_KEY=<your access key> # paste your previously generated access key from the S3 credentials | ||||||
APPFLOWY_S3_SECRET_KEY=<your secret key> # paste your previously generated secret key from the S3 credentials | ||||||
APPFLOWY_S3_BUCKET=appflowy # this isn't really the name of your bucket, but the root folder in your bucket | ||||||
#APPFLOWY_S3_REGION=us-east-1 | ||||||
``` | ||||||
|
||||||
### Step 2.5 - Add and commit your changes | ||||||
|
||||||
Now we use git to store our changes in the git log and make it easier to pull updates from upstream. By using this method every change of defaults in the deploy.env and docker-compose.yml will result in merge conflicts when pulling an update, which you need to resolve before restarting/updating your server. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
git add deploy.env docker-compose.yml | ||||||
git commit -m "my own AppFlowy deployment on Hetzner Cloud" | ||||||
``` | ||||||
|
||||||
## Step 3 | ||||||
|
||||||
Start you AppFlowy Cloud server via docker-compose (or docker compose, depending on your installation method): | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
``` | ||||||
docker-compose --env-file deploy.env up -d | ||||||
``` | ||||||
|
||||||
## Step 4 - Configure AppFlowy App to point to your new server | ||||||
|
||||||
Go into the cloud settings of AppFlowy and change your server to "AppFlowy Cloud Self-hosted". Enable the sync and enter the URL of your cloud server as Base URL. Restart AppFlowy. | ||||||
|
||||||
![Change login server in AppFlowy](images/appflowy_config.png) | ||||||
|
||||||
## Step 5 - User creation and login | ||||||
|
||||||
Open a browser and navigate to the URL of your cloud server. The admin frontend will open up and you can login with the admin credentials you previously defined in the deploy.env. Via the invite page you can now create/invite new users: | ||||||
|
||||||
![Invite new users](images/user_invite.png) | ||||||
|
||||||
The new users receive a magic link for login. In the web frontend you also have the option to directly open AppFlowy with the account you logged into the web frontend with. | ||||||
|
||||||
![Open AppFlowy](images/open_appflowy.png) | ||||||
|
||||||
## Step 6 - Check if the object storage works | ||||||
|
||||||
The object storage will be used for storing images and videos you add in AppFlowy. Open up the AppFlowy application and add an image in a random page. | ||||||
|
||||||
![Add image to a random page in AppFlowy](images/image_appflowy.png) | ||||||
|
||||||
You can now check in you Hetzner Cloud console if the file got created in the bucket. | ||||||
|
||||||
![Check if image is uploaded to the object storage](images/image_console.png) | ||||||
|
||||||
## Conclusion | ||||||
|
||||||
We have setup our own AppFlowy Cloud server using a Hetzner Cloud server and the Hetzner Cloud Object Storage. | ||||||
|
||||||
##### License: MIT | ||||||
|
||||||
<!-- | ||||||
|
||||||
Contributor's Certificate of Origin | ||||||
|
||||||
By making a contribution to this project, I certify that: | ||||||
|
||||||
(a) The contribution was created in whole or in part by me and I have | ||||||
the right to submit it under the license indicated in the file; or | ||||||
|
||||||
(b) The contribution is based upon previous work that, to the best of my | ||||||
knowledge, is covered under an appropriate license and I have the | ||||||
right under that license to submit that work with modifications, | ||||||
whether created in whole or in part by me, under the same license | ||||||
(unless I am permitted to submit under a different license), as | ||||||
indicated in the file; or | ||||||
|
||||||
(c) The contribution was provided directly to me by some other person | ||||||
who certified (a), (b) or (c) and I have not modified it. | ||||||
|
||||||
(d) I understand and agree that this project and the contribution are | ||||||
public and that a record of the contribution (including all personal | ||||||
information I submit with it, including my sign-off) is maintained | ||||||
indefinitely and may be redistributed consistent with this project | ||||||
or the license(s) involved. | ||||||
|
||||||
Signed-off-by: Stefan Weiberg | ||||||
|
||||||
--> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a few links here?