We will start this story with the facts. I am getting older, and I want to move out. As I get older, I am forced to accept more responsibilities, like paying for my own electricity.
As any selfhoster will tell you, this is what bleeds their wallets dry.
Moving to the cloud is not a decision I took lightly, there was alot of consideration put in to this. I was considering purchasing a newer server, probably a Dell r610 or something of that range and maxxing out the specs, but that pulls a fair bit of electricity, and where I plan to live, would also be in the same room as where I sleep. Fun
What cloud provider am I going with?
Well, glad you asked. I have decided to go with a french company called OVH as their prices are pretty hard to beat (at-least from what I have seen)
This article was written before they burnt down their Datacentre, so I am sort of re-evaluating my decisions...
One node costs £3.60 pcm (vat inc) compared to £6 from digital ocean for a similarly specced machine. Not bad eh?
Let's do a cost break down per cloud provider, using their minimum viable product as well as correctly sizing the nodes
I was also considering doing something on GCP with pre-emptible vm's (They get shutdown at any time, moved around, basically abused, for a fraction of the cost)
Below is my ideal setup for moving my stuff off my host at home, to the cloud
Most of the things I run are native web applications, hence why I can slap them on a really basic vm. But, applications like Zabbix and Jellyfin are full blown applications that need COMPUTE! hence why they are on a slightly more powerful host.
Now, the issue I face here is that, I need to in effect, install 13 web apps. I don't really fancy having to do them one by one, so I plan to automate the bajeebus out of it (well, as much as possible)
A nice thing about using something like Ansible is you can see exactly what was done, so if something breaks, I have a rough idea of what the hell is up.
Another nice thing about ansible, is I can create a teardown playbook that dumps databases, copies config files etc to my local host, then allowing me to move cloud providers painlessly.
You can see my setup below.
It's most likely still work in progress, but you can copy parts if you so desire.
Now I am by no means an ansible expert, or a cicd engineer or what have you, but I can google and I'm pretty decent at it.
This ansible playbook works methodically. Below are the steps I am striving towards:
- Install nginx on
rev1
- Install Nginx and mysql on
app1
along with Analytics, Website, kanboard, status page and month server (used for reddit posts) - Install Nginx and mysql on
app2
along with Bookstack, Firefly, Passbolt, Nextcloud and may need to put docker in a container, this I will need to test - Install Zabbix, Jellyfin and Minecraft on
app3
So far I have faced a few issues, mainly down to my own stupidity, and some down to a simple lack of knowledge of ansible.
The first being how I was calling what to install on each server, I had some funky fike structure like you see below.
The issue was you would call the file setup.yml
which would call on the files in the folder called setup
which would then run their respective jobs.
.
├── hosts
├── README.md
├── setup
│ ├── defaults
│ │ └── main.yml
│ ├── group_vars
│ │ ├── all.yml
│ │ ├── app1.yml
│ │ └── app2.yml
│ └── tasks
│ ├── bookstack.yml
│ ├── files
│ │ ├── bookstack_env.j2
│ │ ├── bookstack_nginx.j2
│ │ ├── kanboard_config.j2
│ │ ├── kan_nginx.j2
│ │ ├── matomo_nginx.j2
│ │ ├── status.env.j2
│ │ ├── status.j2
│ │ └── zabbix_apache2.j2
│ ├── ghost.yml
│ ├── - include: nginx.yml
│ ├── jellyfin.yml
│ ├── kanboard.yml
│ ├── main.yml
│ ├── matomo.yml
│ ├── mysql.yml
│ ├── nginx.yml
│ ├── php7.2.yml
│ ├── reboot.yml
│ ├── scripts
│ │ └── inscomp.sh
│ ├── status.yml
│ └── zabbix.yml
├── setup.yml
├── tasks
│ ├── files
│ │ ├── bookstack_env.j2
│ │ ├── bookstack_nginx.j2
│ │ ├── kanboard_config.j2
│ │ ├── kan_nginx.j2
│ │ ├── matomo_nginx.j2
│ │ ├── status.env.j2
│ │ ├── status.j2
│ │ └── zabbix_apache2.j2
│ ├── ghost.yml
│ ├── main.yml
│ └── scripts
│ └── inscomp.sh
└── test
├── defaults
│ └── main.yml
├── hosts
├── roles
│ ├── bookstack
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── common
│ │ └── tasks
│ │ ├── mysql.yml
│ │ └── php7.2.yml
│ ├── defaults
│ │ └── main.yml
│ ├── jellyfin
│ │ └── tasks
│ │ └── main.yml
│ ├── kanboard
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── matomo
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── mysql
│ │ └── tasks
│ │ └── main.yml
│ ├── nginx
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ ├── reboot
│ │ └── tasks
│ │ └── main.yml
│ ├── status
│ │ ├── defaults
│ │ │ └── main.yml
│ │ └── tasks
│ │ └── main.yml
│ └── zabbix
│ └── tasks
│ └── main.yml
└── setup.yml
Now those of you who do ansible day in day our are probably wanting to swat my house, and I'm sorry - You wont like this next part.
My solution on what tasks were to be run per server was so bad, that it actually made me consider giving up.
---
- include: reboot.yml
become: yes
when:
- reboot|bool
- include: nginx.yml
become: yes
delegate_to: app2
when:
- inventory_hostname in groups['app1']
#- inventory_hostname in groups['app2']
- inventory_hostname == app[1]
- inventory_hostname in groups['app1']|default([])
- nginx|bool
tags:
- nginx
This was my attempt at getting it nginx to run on server app1
- Not great.
I asked the kind people of reddit and someone pointed me in the right direction, now everything actually works for a start. So if anyone finds my page from googling 'How to run different playbooks on different servers' (not even close to what I actually needed) then check out how I have done it on github. You're welcome
My second issue I faced was that I use Nginx as I just found it so much simpler to understand. And yes, apache2 and I had a good childhood growing up, but times change
And for some reason Apache2 was being installed when ever I ran the install php7.2 task.
Let's take a look at the task for a second (in breif)
---
- name: Add PHP repository
become: true
apt_repository:
repo: 'ppa:ondrej/php'
tags: [php1]
- name: Update repositories
become: true
apt:
update_cache: yes
tags: [php2]
- name: Install php7.2 #Move to a global install
become: true
apt: name=php7.2 update_cache=yes state=latest
tags: [php3]
- name: Install php7.2-cli #Move to a global install
become: true
apt: name=php7.2-cli update_cache=yes state=latest
tags: [php4]
Now those of you who have been dealing with linux and PHP longer than I've been alive will know exactly what the hell is going on here, something I did not.
So I went to the only place that keeps us Sysadmins employed, google.
Does Apache2 auto install when installing PHP 7.2?
Yes - it does. See, I was installing php7.2
which has a package dependency of... you guessed it libapache2-mod-php7.2
which as far as I care to know, is apache2.
The way I figured this out was really painful, but I ran the playbook with -t php1
then
-t php2
and running systemctl status apache2
till I saw it kick back a response.
My tip for anyone else dealing with weird issues like this? Just segment everything down, read the logs, take it a step at a time. This is the nice thing with ansible is you can see exactly what it did, and there seems to be quite a nice community over at reddit. You dont want to lean on them to spoon feed you, but use them as your last resort! (eg: after page 2 of google)
Now we have the fluff of what I'm doing out of the way, we can finally start running things!
Stay tuned for a part 2!
(Note from the Author: I will probably land up changing a lot of things)
You can hire me via Upwork or emailing me for weekend projects!