Before we deep dive into the step by step process of self-hosting, I would like to share some of the critical terminology and aspects of this installation process.
A quick overview
I'm trying to explain this part as novice as possible to reach the majority of the users. So to all experts => Don't taunt with a better perspective.
Ansible
Things move faster in the realm of less-code and DevOps revolution, which provide more convenience in configuring and managing servers. There exists many Infrastructure as Code (IaC) service providers like Chef, Puppet, Salt-Stack and Ansible. Every one of them has its own architecture and also some Pros & Cons.
From the looks of it, the DEV team has chosen Ansible for its self-hosting repository, maybe because of its simplicity in Writing and Configuring. Ansible doesn't require you to learn any fancy or dependency language. Users write their configuration code in YAML, a human-readable code based on the Python framework.
In this case, the DEV team has done its part by writing the YAML code and sharing it with us.
The required dependencies till now:
- We need to pull the code, so we need
git
. - Ansible runs on Python framework. So the latest version of
Python
. - The Ansible Core (minimum 2.11), So, we need to install
Ansible 4.0.0
Fedora CoreOS
Secondly, for self-hosting Forem, the DEV team chose to use Fedora CoreOS over Ubuntu or other familiar Linux flavours. If you are familiar with enterprise-grade server management like Red Hat Openshift and similar products, you will love this adaptation. If you are not familiar with it, let me highlight some of the key aspects of Fedora CoreOS so that you can stay comfortable during the installation process.
Fedora CoreOS is an
automatically updating
, a minimal operating system for running * containerised workloads* securely and at scale.
Automatically Updating, what else do you want for long term maintenance. Just look at this post and see how easy it is to update to a newer version. (Also, there is no for you to do that patch manually if you are installing via this guide)
Minimal OS with focus on containerisation; It comes with pre-installed Podman and Docker. Also, this is one of the first operating systems, which focus on containerisation.
Fedora CoreOs uses a process called
Ignition
to boot up the machine to our desired state.
Ignition
I'm highly simplifying this part; you can consider Ignition as a process of telling the OS to boot up with these specific configurations => Like, This is my SSH public key (so that I can connect), Here are some files that are used as ENV variables so store them safely(They will persist among different bootups), also finally this is my environment so download them(Like Python, node js, or whatever)
This means that the instant(not precisely, it will download dependencies in the background) your server is up; it is up and running perfectly the way you want it to run. There is no need to download anything manually; this is possible because we define everything in our ignition file.
But, how do we get this ignition file? We use
butane
.
Butane
We have downloaded the self-hosting repository, which contains files based on YML. We first convert them into butane .bu
files (will be stored in a temp folder, don't bother much), and this newly created butane file will be converted into an ignition file .ign
. Now, this .ign file will be ignited during the bootup process.
Don't worry; every step can be automated by Ansible and was awesomely done by the DEV team. All you need to have a few more dependencies for this to work.
Other requirements
-
butane
(Will be used to converting human-readable YML to CoreOS bootable ignition) -
pwgen
(password generator, to generate some ENV variables)
Configuring Requirements
Now we have an idea about the requirements, let's configure them one by one.
- git
- python3
- Ansible
- butane
- pwgen
- doctl => As we are using Digital Ocean
Most of you might already have this, but anyways, I'm including this.
brew install git
Now let's install Python, this is required in order for Ansbile to work properly.
brew install python
This will install python3 in /usr/local/bin/python3
, you can confirm it by using the command which python3
Now as we have Python, we can install Ansible.
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py
python3 -m pip install --upgrade --force-reinstall pip
pip install ansible
python -m pip install argcomplete
autoload -U bashcompinit
bashcompinit
eval $(register-python-argcomplete ansible)
eval $(register-python-argcomplete ansible-config)
eval $(register-python-argcomplete ansible-console)
eval $(register-python-argcomplete ansible-doc)
eval $(register-python-argcomplete ansible-galaxy)
eval $(register-python-argcomplete ansible-inventory)
eval $(register-python-argcomplete ansible-playbook)
eval $(register-python-argcomplete ansible-pull)
eval $(register-python-argcomplete ansible-vault)
Butane is very important, if you are using a ubuntu machine, you should have the latest 21.04 and many other restrictions. Without butane, you cannot move forward.
brew install butane
Just a password generator.
brew install pwgen
doctl allows you to interact with the DigitalOcean API via the command line. We will configure doctl in later part of the guide.
brew install doctl
Towards Self-Hosting
git clone https://github.com/forem/selfhost.git
cd selfhost
pip3 install -r requirements.txt
pwgen -1 24|tee ~/.forem_selfhost_ansible_vault_password
cp inventory/example/setup.yml inventory/forem/setup.yml
Let's edit this file inventory/forem/setup.yml
.
There are ten things you are supposed to edit in this file. Our file has a lot of comments within it; check out the comments for more info. Use some visual text editor
rather than using nano or vim.
Also, don't use the Tab Key
for spacing; YAML is sensitive to spacing, so Always prefer Space Key
- ssh_key => point it to your public key
- ansible_python_interpreter => depends upon your OS
- forem_domain_name => don't include sub-domain
- default_email => Preferably use you domain based email
- forem_subdomain_name => app or www or community
- forem_server_hostname => host or server
-
vault_secret_key_base =>
echo -n $(pwgen -1 128)|ansible-vault encrypt_string --stdin-name vault_secret_key_base
-
vault_imgproxy_key =>
echo -n $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n') | ansible-vault encrypt_string --stdin-name vault_imgproxy_key
-
vault_imgproxy_salt =>
echo -n $(xxd -g 2 -l 64 -p /dev/random | tr -d '\n') | ansible-vault encrypt_string --stdin-name vault_imgproxy_salt
-
vault_forem_postgres_password =>
echo -n $(pwgen -1 128)|ansible-vault encrypt_string --stdin-name vault_forem_postgres_password
Configuring Digital Ocean
We don't need to create a droplet; Ansible will take care of it. All you need to do is:
- Give Digital Ocean access to your Ansible.
- Configure Ansible according to your server requirements.
ansible-galaxy collection install community.digitalocean
Provide your Digital Ocean Auth key, for Ansible to access and create infrastructure. If you don't have one, create it. Now store this value and provide the key by using the following command.
doctl auth init
You can check if you have configured your Digital Ocean properly or not by the following command.
doctl account get
Now it's time to tell Ansible about your server requirements. You can edit both the server size:forem_do_size
and server region: forem_do_region
by changing the respective variables in /playbooks/providers/digitalocean.yml
Provisioning and Configuring our Forem
ansible-playbook -i inventory/forem/setup.yml playbooks/providers/digitalocean.yml
That's it; your Forem will be up and running in around Fifteen to twenty minutes. At the End of the installation process, you can see your IP find the IP address of your Forem Instance.
Configuring DNS
As we now have our Forem IP address, we will point our domain to the IP address. Remember you might have configured this variable, forem_subdomain_name
; we will use it now.
Create an A record
, under your forem_subdomain_name
and point it to your Forem IP Address
without any Proxy(If you don't have this option, don't worry).
Last step
As we configured our domain name, it is time to restart few services to avoid any domain-related issues. For this, we need to connect to our Forem via SSH.
ssh core@<Forem-IP>
We will be in our Fedora CoreOS as a core
user; To restart the service, just use the following command.
sudo systemctl restart forem-traefik.service
Go to your Forem domain name and create your first account. This Forem Admin documentation will help you a lot in configuring your Forem.
Conclusion
I knew it is hard to install Forem in one go, if you are not familiar with few DevOps architecture. But the DEV team made one of the cleanest and optimised playbook, especially for Fedora CoreOS containers. I learnt a lot just by inspecting the playbooks. So rather than being in hurry to install Forem, think of it like a learning adventure.
If you find any issues or have some thing to discuss, you can comment below or If you want some swift response and direct interaction with me, you can ping me here.
Discussion (8)
Nice post. I am a begineer in this dev community, so can you please clear one of my doubts. I have recently installed Forem using Dokku on my Digital Ocean VM or so called droplet by following this tutorial - youtu.be/m4jm2ZOA9bg
Now my question is how can I deploy new code changes into the installed forem. Or how will I update my installed forem with the latest codebase. Please suggest.
Could you redirect this comment to the correct post, I will explain it over there.
Done
Nice article, forem is really hard to install, it's really like learning an adventure, especially someone like me who has just being a WordPress avid user. You have really contributed to forem on GitHub
I hope you will learn soemthing out of it.
Sure, thanks.
Hi @morty ,
Been trying my hands at this tutorial.
But i came across this error that have baffled me.
I'm pretty sure, my secrets have been inserted correctly.
I've checked the line with error but can't seem to find the issue. :( maybe i'm just tunneled vision.
According to the log the issue lies with one of the following
Doctl
was not configured properly