Setting up a development instance of Anki Books
Recently I bought a used computer from my friend. A day after I installed Ubuntu 20.04 from an image I had on a flash drive, I went through all the steps of setting up Anki Books from installing git, configuring a public SSH key on GitHub, cloning, installing system packages, installing Ruby, rbenv, PostgreSQL, and executing Rake scripts to set up the application database. At the very end I realized there was a bug with the bin/dev script and fixed it, pushing the commit up. If you follow these, steps, the commit SHA that fixed that bug was b3421913a68812935f690f2447c53687a3c5280e. This means once you have the repository cloned, you can checkout a detached head at this commit and the app that you start will be the exact same as when I did this. In general though, most of the steps here will apply if you are following this in the future. As I set up the app, I just took notes down on paper to ensure I didn't miss anything. Afterwards I took screenshots of them and have uploaded them here, and this article will explain the pictures in even more detail.
The first thing to do is clone the repository from GitHub. As this is a clean install of Ubuntu, I did not have git installed. When I tried to install git, I got this error and I don't know what that is about. A process is a running instance of a program. Every process has a process ID or PID. In this case, it's saying that there is a process with PID 4708 and for some reason this is causing a problem.
So I just killed the process by sending it a signal. man is a Bash command that you can use to get documentation on Bash commands like kill, cat, ls, cd, and many others. To exit the man page, type the letter q. In the above you can see that I entered the command incorrectly after looking at the man page, and had to look at the man page a second time. Once I got past this whatever this issue was with the process, I installed git with the apt package manager and then I used the up key to go back through the commands to the git clone command. However, now I get something about the authenticity of the IP address of github.com not being recognized. A domain name like github.com is just a human readable alias for an IP address so they are the same. To that, just type yes and press Enter to note that github.com is an IP address that should be trusted.
You will need to login to github.com and add a public SSH key to authenticate.
The ssh-keygen command will generate id_rsa and id_rsa.pub files and the id_rsa.pub is your public key that you can put in GitHub. When I did man ssh, I found it was already installed from the Ubuntu image I guess. When you use ssh-keygen, you will need to make up a "passphrase" and this is something you should manage as you would any other password.
Change directory into the .ssh directory in your home directory and use the cat command to output the contents of that public key file. Copy and paste that for GitHub.
I think this is after we do the git clone, but I forgot to write the git clone again? I guess once you have generated your SSH keys and added the public one to GitHub, you should be able to clone the repo. I put some extra notes explaining about the Dockerfile that is included.
There are a few files in the docs directory at this point in the development history and development.md and postgres.md would be of interest for setting up the app. You might look at the contents of these for some more info. Another good file of interest in the root folder of the project is .ruby-version; this file indicates to rbenv that the Ruby version that should be used for this app is currently 3.2.1. If you execute the command "cat .ruby-version," then you should see the following output: ruby-3.2.1.
There are some packages needed by Active Storage, a part of Rails. These must be installed on the system, so run the sudo apt-get install libvips libvips-tools command and let them install. After that, it is time to install ruby. First you can see that I check if Ruby is installed on the system, and it is not. The output indicates that there are a few ways to get a ruby.
So I choose to install the ruby version manager called rbenv. The other alternative to rbenv is called RVM and I have used both, and I found I like rbenv more than RVM personally but many Ruby developers probably forget which one they use. I get some help with the commands "rbenv --help" and "rbenv install --help" and then do "rbenv install -l" to list the versions. What I find from looking at them is Ruby 3.2.1 is not listed. In order to get more versions to install, the ruby-build tool must be installed. So first I do a sudo apt-get update, but I think I just did this out of instinct and it may not have had much point right now.
Anyway, I visit the github page for ruby-build, and it says to clone the repo and run this script. I do that and then I can use rbenv to install a Ruby 3.2.1. I think I got an error due to a missing package so I install libffi-dev. Then it complains about a different package being missing. If you're wondering how to know what package is missing, you need to notice the log file and take the path and use the cat command to output it, sometimes you need to use less or tail or other commands to look at logs quickly. When I cat a log path I saw, I just looked at the ends and found the package that was missing.
So then I install libyaml-dev which is another package, and tried again. Finally I got Ruby 3.2.1! After a break I install PostgreSQL, the relational database management system used by Anki Books.
I think what I'm doing here is ensuring that the global version of Ruby being used is 3.2.1 and this second command I believe does fix a problem I was having here where starting the app was trying to use a wrong Ruby version. Adding eval "$(rbenv init -)" to the .bashrc file may ensure you do not need to re-run this command every time you get a new shell.
Now I want to do a bundle install. Bundler is a package manager for Ruby libraries, which are also called gems, and it looks at the Gemfile.lock to know which gem versions to install for the app. When I do that, it installs most of the gems but fails to install pg, which is a language binding for using PostgreSQL with Ruby that is needed under the hood by Rails. So then I deduced this was due to a missing package, and I did another install. After that, the bundle install worked and it did succeed in installing all of the gems including pg.
Now to test stuff the connection with the database, I am invoking a command to connect to the Rails console. This is a Ruby read-eval-print loop that loads the application code and connects to the database. However, I think it only connects to the database when it first needs to. I print a hello world and then exit the Rails console. If I had done anything in the Rails console that would have needed data from the database, it probably would have given an error. After this, I run the command "bin/rails db:migrate:status" which shows information about migrations, and I am just doing this to test the connection with the database. It says that the role "regok" does not exist. By default, it is trying to connect as a database user (called a role in PostgreSQL terminology) that corresponds to the user I am logged in as. 5432 is the default port that the PostgreSQL server listens on. So first we need to make sure we have a database user with that name.
The PostgreSQL database installation comes with a user called postgres. To login as them, we can do sudo su to become the super user, and as the super user, do su postgres to become the postgres user, and then we can invoke the command createuser regok to create a user called regok. I think I got an error saying that regok exists, which I'm not too sure about why that happened, but we apparently made the user. If you follow my steps exactly, you will be less efficient than you could be because this would be a good time to alter the regok role to be a superuser. It would also be a good time to add a database called regok. Of course, for you, use your own username. The reason it's good to make a user/role and a database with the same name as your user, is otherwise you need to pass options to the psql command to specify a user and a database to use. It will cause scripts that try to run as you to fail if those do not exist. Anyway, I exit and I try to test the connection with the database again by running the "bin/rails db:migrate:status" command. This time, it says the database does not exist.
So to create the database and seed it with the seed data, it can be done using the "bin/rails db:setup" command. It says the "regok" database does not exist. We could have done this earlier. By default, the initial connection to Postgres seems to be as the user corresponding to the system user and the database connected to also has the same name, so after a new PostgreSQL install, you should make yourself a role and database to avoid these sorts of errors when you just want to connect in. I did a similar thing here where I become the super user, then postgres, and use the createdb command to create a database.
It says that permission is denied. This is why it would have been good to make the regok role a super user earlier. We will need to set up the permissions on the role.
psql is the client CLI for interacting with Postgres. To make myself a super user, I get in there and run the command "ALTER ROLE regok SUPERUSER;" which alters the user to give them the SUPERUSER permission.
Now if we run the command bin/rails db:setup, it creates the databases. All these bin/rails commands are Rake tasks that just come with Rails. It is supposed to sort of have the connotation of GNU Make with Ruby.
Finally, I start the app with bin/dev. I got an error though. This was a configuration drift problem. I made a small correction to the Foreman setup script and committed it. With that small fix, I was able to do the bin/dev script which starts the app. After the app has started up which usually takes less than a minute on my machine, you can visit it using a web browser. Just type localhost:3000 in the web browser address bar. This just means the Ruby on Rails app is listening on port 3000 to requests from your machine's IP address which it represents to itself as localhost.
If you log in, you can make articles on whatever you want to
Article notes
What Ruby version manager does Anki Books recommend?
rbenv
What file in Anki Books tells rbenv the Ruby version?
.ruby-version
What database does Anki Books use that is the best open-source relational database management system since Oracle took over MySQL?
PostgreSQL
What is it called when you checkout a lone commit instead of a branch, and not in a branch?
A detached head
What could be simply defined as a running program?
A process
What is the CLI for manual pages in a Bash shell?
man
What letter is to exit a man page on Linux?
q
What package manager on Ubuntu could you use to install git?
apt
What command can you use to generate ssh keys on a Ubuntu machine for example?
ssh-keygen
What directory in your home directory is where the ssh-keygen command puts your id_rsa.pub and private key?
.ssh
What file in the Anki Books source is infrastructure as code (1 file) that specifies a Docker container that can run Anki Books?
Dockerfile
What is the other main Ruby version manager (not rbenv)?
RVM