Install Reactive Resumes
Installing Reactive Resumes
Setup a Server
In most self hosted applications these days, you'll need a machine to act as a server. This can be a machine in your home / business (such as an old laptop or desktop, a Raspberry PI or Single Board Computer (SBC), or even the computer you're reading this article from), a VM / Container hosted on one of your machines, or a VPS (Virtual Private Server) hosted by companies like RackNerd, Digital Ocean, Linode, Vultr, and so many more.
Regardless of which option you choose, you'll want to do a few things to get the server setup properly.
Install updates to our Server
Ubuntu / Debian
sudo apt update && sudo apt upgrade -y
RedHat / CentOS / Fedora / Alma / Rocky
sudo dnf update -y
Add a non-root / sudo user on the server
Generally, when you setup a new server, the VPS (Virtual Private Server) service sets up a default "root" user for you. It's considered unsafe to do everything as "root", so let's setup a non-root user who has super user (sudo) privileges.
adduser <username>
You'll be prompted to enter and confirm a password for this user. You'll also be asked for some user information like Name, etc, but this is not required information. At the end, confirm the entries, and you'll have your new user.
Next, we need to add the user to the super user group.
Ubuntu / Debian
usermod -aG sudo <username>
RedHat / CentOS / Fedora / Alma / Rocky
usermod -aG wheel <username>
Now, you can log out of the system, and log back in as your new non-root super user.
Install Docker and Docker Compose
Fortunately, there is a single line command that will install both Docker and Docker Compose for us on most Linux based distributions.
We need the 'curl' utility to get this to work, so if you don't have it, you'll want to install it first with
Ubuntu / Debian
sudo apt install curl -y
RedHat / CentOS / Fedora / Alma / Rocky
sudo dnf install curl -y
Next, we'll run the command to install Docker and Docker Compose:
curl https://get.docker.com | sh
You may be prompted to enter your super user password, so be ready for it. Once you do, the install should proceed.
Once complete. we want to add our user to the 'docker' group so we can do docker
and docker compose
commands without having to type in sudo
each time.
sudo usermod -aG docker <username>
Now we'll logout / exit the session, and log right back in so the updated group will take effect.
Installing ReactiveResume
Let's create a folder structure in our server to help us get everything organized. From your home directory (you can use cd
to go back to your home directory) we'll create a directroy called 'docker', and within it a directory called 'resumes'.
mkdir -p docker/resumes
This command tells the system to create the 'docker' folder if one doesn't already exist, but if it does, then use it. Then it tells the system to create a folder named 'resumes' within the 'docker' folder if one doesn't already exist.
Now we'll move into our new folder with
cd docker/resumes
Finally, we'll create a new file called "compose.yaml" where we'll setup our application configurations.
nano compose.yaml
# In this Docker Compose example, it assumes that you maintain a reverse proxy externally (or chose not to).
# The only two exposed ports here are from minio (:9000) and the app itself (:3000).
# If these ports are changed, ensure that the env vars passed to the app are also changed accordingly.
services:
# Database (Postgres)
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- ./postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: aL0n6Str0n6Pa5sw0rdtHa7isH4rdtoGu3s5
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
interval: 10s
timeout: 5s
retries: 5
# Storage (for image uploads)
minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data
ports:
- "9000:9000"
volumes:
- ./minio_data:/data
environment:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: aDiff3r3n7L0n6Str0n6Pas5w0rd
# Chrome Browser (for printing and previews)
chrome:
image: ghcr.io/browserless/chromium:v2.18.0 # Upgrading to newer versions causes issues
restart: unless-stopped
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
TIMEOUT: 10000
CONCURRENT: 10
TOKEN: chrome_token
EXIT_ON_HEALTH_FAILURE: "true"
PRE_REQUEST_HEALTH_CHECK: "true"
app:
image: amruthpillai/reactive-resume:latest
restart: unless-stopped
ports:
- "3000:3000"
depends_on:
- postgres
- minio
- chrome
environment:
# -- Environment Variables --
PORT: 3000
NODE_ENV: production
# -- URLs --
PUBLIC_URL: http://[your-server-ip]:3000 # alternatively the fqdn you want to access the site with
STORAGE_URL: http://[your-server-ip]:9000/default # alternatively the fqdn you want to access the site with
# -- Printer (Chrome) --
CHROME_TOKEN: chrome_token
CHROME_URL: ws://chrome:3000
# -- Database (Postgres) --
DATABASE_URL: postgresql://postgres:aL0n6Str0n6Pa5sw0rdtHa7isH4rdtoGu3s5@postgres:5432/postgres
# -- Auth --
ACCESS_TOKEN_SECRET: [use the command 'openssl rand base64 32' to generate a token, then copy and paste it here]
REFRESH_TOKEN_SECRET: [use the command 'openssl rand base64 32' to generate another token, then copy and paste it here]
# -- Emails --
# if you want email to work, you need to umcomment the SMTP_URL line, and replace the smtp url with the details of your email provider and account.
MAIL_FROM: noreply@localhost
# SMTP_URL: smtp://user:pass@smtp:587 # Optional
# -- Storage (Minio) --
STORAGE_ENDPOINT: minio
STORAGE_PORT: 9000
STORAGE_REGION: us-east-1 # Optional
STORAGE_BUCKET: default
STORAGE_ACCESS_KEY: minioadmin
STORAGE_SECRET_KEY: aDiff3r3n7L0n6Str0n6Pas5w0rd
STORAGE_USE_SSL: "false"
STORAGE_SKIP_BUCKET_CHECK: "false"
# -- Crowdin (Optional) --
# CROWDIN_PROJECT_ID:
# CROWDIN_PERSONAL_TOKEN:
# -- Email (Optional) --
DISABLE_SIGNUPS: "false" # change to true if you don't want other users signing up (recommend you change it after you sign up your first user), and restart the container)
DISABLE_EMAIL_AUTH: "true" # change to false if you are setting up smtp email and want email authentication
# -- GitHub (Optional) --
# GITHUB_CLIENT_ID: github_client_id
# GITHUB_CLIENT_SECRET: github_client_secret
# GITHUB_CALLBACK_URL: http://localhost:3000/api/auth/github/callback
# -- Google (Optional) --
# GOOGLE_CLIENT_ID: google_client_id
# GOOGLE_CLIENT_SECRET: google_client_secret
# GOOGLE_CALLBACK_URL: http://localhost:3000/api/auth/google/callback
# -- OpenID (Optional) --
# VITE_OPENID_NAME: OpenID
# OPENID_AUTHORIZATION_URL:
# OPENID_CALLBACK_URL: http://localhost:3000/api/auth/openid/callback
# OPENID_CLIENT_ID:
# OPENID_CLIENT_SECRET:
# OPENID_ISSUER:
# OPENID_SCOPE: openid profile email
# OPENID_TOKEN_URL:
# OPENID_USER_INFO_URL:
In the above file you really need to change some values before using this file.
-
Anything with a pound sign / hashtag in front of it is a "comment", which means it's ignored by docker.
-
Change the password values for Postrgres and Minio. Note that these values are located in 2 places each, and the values for Postgres must match each other, and the values for Minio must match each other. The values for Postgres vs Minio should be different though.
-
You can use a command line command to generate the values for the ACCESS_TOKEN_SECRET and the REFRESH_TOKEN_SECRET. The command is
openssl rand base64 32
-
If you want email in the system, you can change the MAIL_FROM address, and uncomment the SMTP_URL line, and replace the placeholder URL with your actual SMTP URL. The way it works is
smtp://<youremailuser>:<youremailpassword>@<yoursmtphosturl>:<yoursmtpportnumber>
. -
If you want to disable signups for the site, you can change the value to 'true', but I suggest you do that after you have registered your first user, then restart the containers.
Once finished making your changes, use CTRL + O to save your changes, press Enter to confirm, and exit the nano editor with CTRL + X.
Pull the Docker Images
docker compose pull
Start the Containers and Follow the Logs
Now we'll start up our application, and follow the logs briefly, just to watch for any errors. We can do this by concatenating two commands into one line.
docker compose up -d && docker compose logs -f
This will start your containers, and then show the log output as they start up. It will scroll by very fast, but we are just watching for anything we think may be an error.
If all has gone well, you should see a line that says the server has started, and is now accessible at an address and port.
This means we are able to go to our browser, and enter the IP address of our server, and the port number you specified in the port mapping. In my case I left the port at 3000, so I went to my server's IP with port 3000 like this:
http://192.168.10.84:3000
This brought me to the start page. You'll see the option to sign in, so click on it. Next, we need to create a new account. You should see a link to create a new account just above the username field. Click on it, then fill in the form with your name, username, email, and a password for the new account, then click 'Create'.
You can now start adding a new Resume.
Disable Sign Up
If you want to disable sign up now, then you can go back to the compose.yaml
file, and you can change the value for DISABLE_SIGNUPS to be "true", then save your changes. Now restart the containers with
docker compose up -d --force-recreate
Don't worry, none of your data will be lost.
No Comments