Dirt Cheap Boot
Tags: springboot, cloud, infrastructure, tutorial
Published: 2021-01-30 17:25:57

---
title: Dirt Cheap Boot
published: true
description: Host Spring Boot on DigitalOcean or similar for as little as $5/month.
tags: springboot, cloud, infrastructure, tutorial
cover_image: https://miro.medium.com/max/1400/1*g_b5cBI5f7n2Op3M1yIH8A.png
---

Gather round as we embark on a journey about how you can host your very own fully fledged Spring Boot web application (API and Frontend) for as little as $5/month.

I would like for this guide to be as comprehensive as possible. So if you have questions about how to get from point A to point B, please leave a comment.
Oh, and if something here was helpful to you, remember to bookmark this guide so you can find it again.

if you would like to see the projects I'm running using this technique check them out!
https://parrit.io
https://plenti.dev

#### What You Need
- A spring boot web application that can run on your localhost machine

# Step 1: The Accounts
We’re going to be signing up for a variety of accounts to piece together all of the various services you’re going to be using. _(Note: this simply the best, cheapest list of technologies I’ve found so far. If you have betters or alternatives, leave a comment below!)_

Database: [elephantsql](https://www.elephantsql.com/) (free)

Hosting: [digitalocean](https://www.digitalocean.com/) ($5/month)

CI/CD: [codeship](https://codeship.com/) (free)

# Step 2: Environments
Part of what is going to be so great about the finished product is the ability to use various environments all linked to their own git branches. Codeship is will be able to read the git branch and publish using the environment you specify.

Here is my short writeup on environments. Follow this if you’re looking to set up staging versus production versus development and don’t already know how (or need a refresher)

https://anthony-orange.medium.com/development-environments-in-spring-boot-dfda98833752

# Step 3: Configuring the Database
Externalized databases running on separate servers than your application is a good idea. In order to get there, you’re going to need your localhost application to be using a local database instance. Here’s my guide for how to do that: https://medium.com/@anthonyjamesdreessen/externalized-postgres-in-spring-boot-9043de80a7df

Once we’re configured to do that, we want to use a remote database instance. We can do that through our environments!

Here is a template of what a finished environment might look like

```
spring.datasource.url=jdbc:postgresql://dbname.db.elephantsql.com:5432/db_user_name
spring.datasource.username=db_user_name
spring.datasource.password=password
```

# Step 4: Launching the Application

### Logging in through SSH
First, make sure you can ssh into your droplet. You’re going to need get it set up so you don’t have to enter in the password every time. Check out this article for a how-to: https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/

_(tl;dr add your computer’s public key `~/.ssh/id_rsa.pub` to your server’s `~/.ssh/authorized_keys`)_

### Installing Java
An important step. DigitalOcean droplets don’t necessarily come with Java already installed.
1. Update your apt-get
2. Check out if your machine does `java -version` if nothing is installed, you should be shown commands for how to do so. The default method is `sudo apt install default-jre`

### Copy your application to your droplet
copy over your `.jar` file to the droplet `scp path/to/jar username@ip_address:` **make sure you add the colon.**

Then, after ssh-ing into your server, you can verify that your program works by running `/usr/bin/java -jar -Dspring.profiles.active=profile myapp.jar` _(Note: don’t use this for your production deployment method. There’s something better in the next section)_

you should see the familiar Spring Boot startup console. navigate to `<droplet_ip>:8080` in your browser/client to see it working.

# Step 5: Starting your application remotely through SSH
Modern Linux distros use systemd for deploying things like a Spring Boot application. In order to get it set up, you have to do some configuration on your droplet. I have instructions below, but if you want more information about this topic, click [here](https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#deployment-systemd-service)

While ssh-ed into your droplet:

### Create a service definition for your application

1. `sudo vi /etc/systemd/system/myapp.service`
2. The service definition file should look something like this

```
[Unit]
Description=My Java Application
After=syslog.target

[Service]
Environment="MY_DATABASE_PASSWORD=<database_password>"
User=<droplet_username>
ExecStart=/usr/bin/java -Xmx256m -Dspring.profiles.active=<profile> -jar /home/<droplet_username>/myapp.jar
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
```
3. Run `systemctl daemon-reload`

4. Test that the service is able to run the app manually by using the command `systemctl start myapp` _(Note: since systemctl knows to look for the extension `.service` you don’t need to append it to myapp, but you can)_

If step #4 fails, you can see what went wrong by using systemctl status myapp

### Bake in SU access

Now if you'll notice, when when we run the `systemctl start myapp` command, we are interactively asked for our password. This will break any attempt to do this from an automated shell script which makes it difficult to automate our deploys on Codeship.

In order to work around this, we specify exactly one command (the restart command) that our particular user is going to be able to execute without needing to enter a password. This remains a secure (enough) thing to do because we still have the SSH key for login into the droplet.

1. `sudo vi /etc/sudoers.d/myapp`
2. add this line `<username> ALL = NOPASSWD: /bin/systemctl restart myapp`

__**IMPORTANT: The value of myapp in the above must not contain any word boundaries. This mean no periods `.` and no hyphens `-`__

# Step 6: Deploying automatically with Codeship

### Add ssh access to your codeship account

This is very similar to what we did in step 4. In fact, you're simply going to append to the file we modified in step 4. You can find CodeShip's SSH key in `Builds => Project Settings (gear icon) => General => Keys`

### Create deployment script on Codeship
In the deploy settings on your Codeship project. We're going to want to use a custom script. The most basic version of this looks like this:

```
./gradlew bootJar
scp build/libs/myapp.jar username@ip_address:
ssh -t username@ip_address 'sudo /bin/systemctl restart myapp'
```

This script does the following:
- builds the jar
- copies it over like we did last time
- executes the `restart` command for `systemd` to restart our service that we defined above

# Success!
If I’ve successfully guided you then after your build goes green then you should be able to push code to a repository and have it trigger an automatic deploy to the cloud!

Again, if you would like more explanation about how to get from point A to point B please leave a comment and I’ll be sure to get more thorough.